# -*- coding: UTF-8 -*-
import pymysql
import time, datetime
import numpy as np
import traceback
import logging
import os, sys
####################################
# 全局变量
# 数据库相关
g_DatabaseIP = '192.168.10.9'   # ANTS的内部IP，正式版本
# g_DatabaseIP = '47.244.42.149'   #mg.acciot.com.tw 台湾的，正式版本
# g_DatabaseIP = '139.196.238.229'   #106.14.209.254 上海，测试版本
# g_DatabaseIP = '114.34.200.59'   # 114.34.200.59 ants tw，测试版本
dbport = 3306   #数据库默认端口就是3306，连接数据库时，不需要指定
dbuser = 'ants' # user
dbpasswd = 'Aitrip123'    # password
database = 'ants'   # database

# 时间相关的全局变量
g_PerDayWorkingTime = 8  # 每天的工作时间，单位都是小时
g_PerWeekWorkingDays = 5  # 每周有几天工作日
g_MorningStartWorktime = '8:30'  # 上午工作开始时间
g_MorningEndWorktime = '12:00'  # 上午工作结束时间
g_AfternoonStartWorktime = '13:00'  # 下午工作开始时间
g_AfternoonEndWorktime = '17:30'  # 下午工作结束时间，实际上是17:30下班，如果开始时间在17:00到17:30，再安排计划无意义，要安排到下一天
g_LastCanArrageWorktime = '17:00'   # 可以被安排的最后的时间，如果该工序需要半小时，就要安排到下一天开始
g_NoonRestTime = 1.0  # 中午休息的时间段：1.0小时
g_NightRestTime = 15  # 晚上下班到第二天上午上班的时间段：15小时
# 制程相关的全局变量
g_MaxProcedure_num = 12  # 每个工单里最大的制程数是12
g_AlartWorkorder_DiffDays = 1 # 急单就是距离当前时间，最迟开始的时间不超过1天

g_DeviceTypeID2ab_disc = {}  # a/b的值    对应每个devicetypeID的阀值
g_allVk_v = ()  # 所有人的休假日元组
####################################

g_countTest = 0  # 测试变量
g_countTest1 = 0  # 测试变量

# 分批上传数据库
def batchUploadtoDB(sql, mylist, oneUploadNum = 50):
    if len(mylist) == 0:
        return False

    conn = pymysql.Connect(
        host=g_DatabaseIP,
        port=dbport,
        user=dbuser,
        passwd=dbpasswd,
        db=database,
        charset='utf8',
        local_infile=1
    )
    # 使用cursor()方法获取操作游标
    cursor = conn.cursor()

    toList = []
    for i in range(1, len(mylist)+1):
        if i % oneUploadNum == 0:   # 累积到数量了，要上传
            try:
                (ret, conn, cursor) = _reConn(conn, cursor)
                if (ret == False):
                    return False
                result = cursor.executemany(sql, toList)
                toList = []  # 列表初始化
            except:
                return False
        toList.append(mylist[i-1])
    # 把余下来的数据也上传
    if len(toList) > 0:
        try:
            (ret, conn, cursor) = _reConn(conn, cursor)
            if (ret == False):
                return False
            result = cursor.executemany(sql, toList)
        except:
            return False
    # 数据库关闭
    conn.commit()
    cursor.close()
    conn.close()
    return True

def _conn(conn, cursor):
    try:
        conn = pymysql.Connect(
            host=g_DatabaseIP,
            port=dbport,
            user=dbuser,
            passwd=dbpasswd,
            db=database,
            charset='utf8',
            local_infile=1
        )
        cursor = conn.cursor()
        cursor.execute('SET SESSION WAIT_TIMEOUT = 86400')

        return (True, conn, cursor)
    except:
        return (False, conn, cursor)

def _reConn(conn, cursor, num=3, stime=1):  # 重试连接总次数为1天,这里根据实际情况自己设置,如果服务器宕机1小时都没发现就......
    _number = 0
    _status = True
    ret = True
    while _status and _number <= num:
        try:
            try:
                conn.ping()  # cping 校验连接是否异常
            except:
                conn.ping(True) # 在使用ping()的时候，可能由于版本问题出现ping()函数需要参数，从而发生异常
            _status = False
        except:
            (ret, conn, cursor) = _conn(conn, cursor)
            if ret == True:  # 重新连接,成功退出
                _status = False
                break
            _number += 1
            time.sleep(stime)  # 连接不成功,休眠3秒钟,继续循环，知道成功或重试次数结束
    if(_number > num):
        # False
        return (False, conn, cursor)

    return (True, conn, cursor)

####################################
# 1.把datetime转成字符串
# 2.只到分
def datetime_toString(dt):
    # print("1.把datetime转成字符串: ", dt.strftime("%Y-%m-%d %H:%M"))
    if isinstance(dt, datetime.date):
        if dt != None:
            return dt.strftime("%Y-%m-%d %H:%M")

    return ("0000-00-00 00:00")

    #return dt.strftime("%m月%d日")

# 2.把字符串转成datetime
def string_toDatetime(st):
    if isinstance(st, unicode):
        st = st.encode("gbk")
    if isinstance(st, str):
        if st != "0000-00-00 00:00:00" and st != "0000-00-00 00:00" and st is not None:
            if len(st) > 16:
                return datetime.datetime.strptime(st, "%Y-%m-%d %H:%M:%S")
            else:
                return datetime.datetime.strptime(st, "%Y-%m-%d %H:%M")
    else:
        return st   # 不处理
    return None

# 把时间戳转化为时间: 1479264792 to 2016-11-16 10:53:12
def TimeStampToTime(timestamp):
    timeStruct = time.localtime(timestamp)
    return time.strftime('%Y-%m-%d %W %H:%M', timeStruct)

# 3.把字符串转成时间戳形式
def string_toTimestamp(st):
    # print("3.把字符串转成时间戳形式:", time.mktime(time.strptime(st, "%Y-%m-%d %H:%M:%S")))
    return time.mktime(time.strptime(st, "%Y-%m-%d %H:%M"))
    #return time.mktime(time.strptime(st, "%Y-%m-%d"))

# 4.把时间戳转成字符串形式
def timestamp_toString(sp):
    # print("4.把时间戳转成字符串形式: ", time.strftime("%Y-%m-%d %H:%M", time.localtime(sp)))
    return time.strftime("%Y-%m-%d %H:%M", time.localtime(sp))

# 5.把datetime类型转外时间戳形式
def datetime_toTimestamp(dt):
    # print("5.把datetime类型转外时间戳形式:", time.mktime(dt.timetuple()))
    return time.mktime(dt.timetuple())

# 数据库关联的总表
class AllViewResultClass:
    def __init__(self):
        self.id = 0                 # procedure_ID
        self.workorder_id = 0       # 工单ID
        self.devicetype_id = 0      # 制程ID
        self.workorder_finishdate = None  # 工单预计完成时间
        self.PDName = None      # 制程名称
        self.manhours = None    # 制程所需时间
        self.yjkg = 0           # 预计开工日
        self.WOName = None      # 工单名称
        self.num = None         # 工单个数
        self.finishnum = None   # 工单已经完成的制程数
        self.maxnum = None      # 工单总的制程数
        self.overtime_hours = 0.0   # 超过的最后的时间，即：加班工时
        self.procedure1_id = None  # 第1制程ID
        self.procedure2_id = None  # 第2制程ID
        self.procedure3_id = None  # 第3制程ID
        self.procedure4_id = None  # 第4制程ID
        self.procedure5_id = None  # 第5制程ID
        self.procedure6_id = None  # 第6制程ID
        self.procedure7_id = None  # 第7制程ID
        self.procedure8_id = None  # 第8制程ID
        self.procedure9_id = None  # 第9制程ID
        self.procedure10_id = None  # 第10制程ID
        self.procedure11_id = None  # 第11制程ID
        self.procedure12_id = None  # 第12制程ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = 0.0  # 制程1所需时间
        self.procedure2_manhours = 0.0  # 制程2所需时间
        self.procedure3_manhours = 0.0  # 制程3所需时间
        self.procedure4_manhours = 0.0  # 制程4所需时间
        self.procedure5_manhours = 0.0  # 制程5所需时间
        self.procedure6_manhours = 0.0  # 制程6所需时间
        self.procedure7_manhours = 0.0  # 制程7所需时间
        self.procedure8_manhours = 0.0  # 制程8所需时间
        self.procedure9_manhours = 0.0  # 制程9所需时间
        self.procedure10_manhours = 0.0  # 制程10所需时间
        self.procedure11_manhours = 0.0  # 制程11所需时间
        self.procedure12_manhours = 0.0  # 制程12所需时间
        self.procedure1_preparedate = 0.0  # 原料1备齐日
        self.procedure2_preparedate = 0.0  # 原料2备齐日
        self.procedure3_preparedate = 0.0  # 原料3备齐日
        self.procedure4_preparedate = 0.0  # 原料4备齐日
        self.procedure5_preparedate = 0.0  # 原料5备齐日
        self.procedure6_preparedate = 0.0  # 原料6备齐日
        self.procedure7_preparedate = 0.0  # 原料7备齐日
        self.procedure8_preparedate = 0.0  # 原料8备齐日
        self.procedure9_preparedate = 0.0  # 原料9备齐日
        self.procedure10_preparedate = 0.0  # 原料10备齐日
        self.procedure11_preparedate = 0.0  # 原料11备齐日
        self.procedure12_preparedate = 0.0  # 原料12备齐日
        self.procedure1_mannum = 0.0  # 原料1人数
        self.procedure2_mannum = 0.0  # 原料2人数
        self.procedure3_mannum = 0.0  # 原料3人数
        self.procedure4_mannum = 0.0  # 原料4人数
        self.procedure5_mannum = 0.0  # 原料5人数
        self.procedure6_mannum = 0.0  # 原料6人数
        self.procedure7_mannum = 0.0  # 原料7人数
        self.procedure8_mannum = 0.0  # 原料8人数
        self.procedure9_mannum = 0.0  # 原料9人数
        self.procedure10_mannum = 0.0  # 原料10人数
        self.procedure11_mannum = 0.0  # 原料11人数
        self.procedure12_mannum = 0.0  # 原料12人数
    def clear(self):
        self.id = 0                 # procedure_ID
        self.workorder_id = 0       # 工单ID
        self.devicetype_id = 0      # 制程ID
        self.workorder_finishdate = None  # 工单预计完成时间
        self.PDName = None      # 制程名称
        self.manhours = None    # 制程所需时间
        self.yjkg = 0           # 预计开工日
        self.WOName = None      # 工单名称
        self.num = None         # 工单个数
        self.finishnum = None   # 工单已经完成的制程数
        self.maxnum = None      # 工单总的制程数
        self.overtime_hours = 0.0   # 超过的最后的时间，即：加班工时
        self.procedure1_id = None  # 第1制程ID
        self.procedure2_id = None  # 第2制程ID
        self.procedure3_id = None  # 第3制程ID
        self.procedure4_id = None  # 第4制程ID
        self.procedure5_id = None  # 第5制程ID
        self.procedure6_id = None  # 第6制程ID
        self.procedure7_id = None  # 第7制程ID
        self.procedure8_id = None  # 第8制程ID
        self.procedure9_id = None  # 第9制程ID
        self.procedure10_id = None  # 第10制程ID
        self.procedure11_id = None  # 第11制程ID
        self.procedure12_id = None  # 第12制程ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = 0.0  # 制程1所需时间
        self.procedure2_manhours = 0.0  # 制程2所需时间
        self.procedure3_manhours = 0.0  # 制程3所需时间
        self.procedure4_manhours = 0.0  # 制程4所需时间
        self.procedure5_manhours = 0.0  # 制程5所需时间
        self.procedure6_manhours = 0.0  # 制程6所需时间
        self.procedure7_manhours = 0.0  # 制程7所需时间
        self.procedure8_manhours = 0.0  # 制程8所需时间
        self.procedure9_manhours = 0.0  # 制程9所需时间
        self.procedure10_manhours = 0.0  # 制程10所需时间
        self.procedure11_manhours = 0.0  # 制程11所需时间
        self.procedure12_manhours = 0.0  # 制程12所需时间
        self.procedure1_preparedate = 0.0  # 原料1备齐日
        self.procedure2_preparedate = 0.0  # 原料2备齐日
        self.procedure3_preparedate = 0.0  # 原料3备齐日
        self.procedure4_preparedate = 0.0  # 原料4备齐日
        self.procedure5_preparedate = 0.0  # 原料5备齐日
        self.procedure6_preparedate = 0.0  # 原料6备齐日
        self.procedure7_preparedate = 0.0  # 原料7备齐日
        self.procedure8_preparedate = 0.0  # 原料8备齐日
        self.procedure9_preparedate = 0.0  # 原料9备齐日
        self.procedure10_preparedate = 0.0  # 原料10备齐日
        self.procedure11_preparedate = 0.0  # 原料11备齐日
        self.procedure12_preparedate = 0.0  # 原料12备齐日
        self.procedure1_mannum = 0.0  # 原料1人数
        self.procedure2_mannum = 0.0  # 原料2人数
        self.procedure3_mannum = 0.0  # 原料3人数
        self.procedure4_mannum = 0.0  # 原料4人数
        self.procedure5_mannum = 0.0  # 原料5人数
        self.procedure6_mannum = 0.0  # 原料6人数
        self.procedure7_mannum = 0.0  # 原料7人数
        self.procedure8_mannum = 0.0  # 原料8人数
        self.procedure9_mannum = 0.0  # 原料9人数
        self.procedure10_mannum = 0.0  # 原料10人数
        self.procedure11_mannum = 0.0  # 原料11人数
        self.procedure12_mannum = 0.0  # 原料12人数
    def to_list(self):
        return [self.id, self.workorder_id, self.devicetype_id, self.workorder_finishdate, self.PDName,
                self.manhours, self.yjkg, self.WOName, self.num, self.finishnum, self.maxnum, self.overtime_hours,
                self.procedure1_id, self.procedure2_id, self.procedure3_id, self.procedure4_id,
                self.procedure5_id, self.procedure6_id, self.procedure7_id, self.procedure8_id,
                self.procedure9_id, self.procedure10_id, self.procedure11_id, self.procedure12_id,
                string_toDatetime(self.procedure1_startdate), string_toDatetime(self.procedure2_startdate),
                string_toDatetime(self.procedure3_startdate), string_toDatetime(self.procedure4_startdate),
                string_toDatetime(self.procedure5_startdate), string_toDatetime(self.procedure6_startdate),
                string_toDatetime(self.procedure7_startdate), string_toDatetime(self.procedure8_startdate),
                string_toDatetime(self.procedure9_startdate), string_toDatetime(self.procedure10_startdate),
                string_toDatetime(self.procedure11_startdate), string_toDatetime(self.procedure12_startdate),
                string_toDatetime(self.procedure1_finishdate), string_toDatetime(self.procedure2_finishdate),
                string_toDatetime(self.procedure3_finishdate), string_toDatetime(self.procedure4_finishdate),
                string_toDatetime(self.procedure5_finishdate), string_toDatetime(self.procedure6_finishdate),
                string_toDatetime(self.procedure7_finishdate), string_toDatetime(self.procedure8_finishdate),
                string_toDatetime(self.procedure9_finishdate), string_toDatetime(self.procedure10_finishdate),
                string_toDatetime(self.procedure11_finishdate), string_toDatetime(self.procedure12_finishdate),
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                string_toDatetime(self.procedure1_preparedate), string_toDatetime(self.procedure2_preparedate),
                string_toDatetime(self.procedure3_preparedate), string_toDatetime(self.procedure4_preparedate),
                string_toDatetime(self.procedure5_preparedate), string_toDatetime(self.procedure6_preparedate),
                string_toDatetime(self.procedure7_preparedate), string_toDatetime(self.procedure8_preparedate),
                string_toDatetime(self.procedure9_preparedate), string_toDatetime(self.procedure10_preparedate),
                string_toDatetime(self.procedure11_preparedate), string_toDatetime(self.procedure12_preparedate),
                self.procedure1_mannum, self.procedure2_mannum, self.procedure3_mannum, self.procedure4_mannum,
                self.procedure5_mannum, self.procedure6_mannum, self.procedure7_mannum, self.procedure8_mannum,
                self.procedure9_mannum, self.procedure10_mannum, self.procedure11_mannum,self.procedure12_manhours]
    def __list__(self):
        return [self.id, self.workorder_id, self.devicetype_id, self.workorder_finishdate, self.PDName,
                self.manhours, self.yjkg, self.WOName, self.num, self.finishnum, self.maxnum, self.overtime_hours,
                self.procedure1_id, self.procedure2_id, self.procedure3_id, self.procedure4_id,
                self.procedure5_id, self.procedure6_id, self.procedure7_id, self.procedure8_id,
                self.procedure9_id, self.procedure10_id, self.procedure11_id, self.procedure12_id,
                string_toDatetime(self.procedure1_startdate), string_toDatetime(self.procedure2_startdate),
                string_toDatetime(self.procedure3_startdate), string_toDatetime(self.procedure4_startdate),
                string_toDatetime(self.procedure5_startdate), string_toDatetime(self.procedure6_startdate),
                string_toDatetime(self.procedure7_startdate), string_toDatetime(self.procedure8_startdate),
                string_toDatetime(self.procedure9_startdate), string_toDatetime(self.procedure10_startdate),
                string_toDatetime(self.procedure11_startdate), string_toDatetime(self.procedure12_startdate),
                string_toDatetime(self.procedure1_finishdate), string_toDatetime(self.procedure2_finishdate),
                string_toDatetime(self.procedure3_finishdate), string_toDatetime(self.procedure4_finishdate),
                string_toDatetime(self.procedure5_finishdate), string_toDatetime(self.procedure6_finishdate),
                string_toDatetime(self.procedure7_finishdate), string_toDatetime(self.procedure8_finishdate),
                string_toDatetime(self.procedure9_finishdate), string_toDatetime(self.procedure10_finishdate),
                string_toDatetime(self.procedure11_finishdate), string_toDatetime(self.procedure12_finishdate),
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                string_toDatetime(self.procedure1_preparedate), string_toDatetime(self.procedure2_preparedate),
                string_toDatetime(self.procedure3_preparedate), string_toDatetime(self.procedure4_preparedate),
                string_toDatetime(self.procedure5_preparedate), string_toDatetime(self.procedure6_preparedate),
                string_toDatetime(self.procedure7_preparedate), string_toDatetime(self.procedure8_preparedate),
                string_toDatetime(self.procedure9_preparedate), string_toDatetime(self.procedure10_preparedate),
                string_toDatetime(self.procedure11_preparedate), string_toDatetime(self.procedure12_preparedate),
                self.procedure1_mannum, self.procedure2_mannum, self.procedure3_mannum, self.procedure4_mannum,
                self.procedure5_mannum, self.procedure6_mannum, self.procedure7_mannum, self.procedure8_mannum,
                self.procedure9_mannum, self.procedure10_mannum, self.procedure11_mannum, self.procedure12_manhours]

# 更新fa_aps_planlog类，只有更新，没有插入
class UpdatePlanlogClass:
    def __init__(self):
        self.procedure1_man_id = 0  # 人员1：ID
        self.procedure2_man_id = 0  # 人员2：ID
        self.procedure3_man_id = 0  # 人员3：ID
        self.procedure4_man_id = 0  # 人员4：ID
        self.procedure5_man_id = 0  # 人员5：ID
        self.procedure6_man_id = 0  # 人员6：ID
        self.procedure7_man_id = 0  # 人员7：ID
        self.procedure8_man_id = 0  # 人员8：ID
        self.procedure9_man_id = 0  # 人员9：ID
        self.procedure10_man_id = 0  # 人员10：ID
        self.procedure11_man_id = 0  # 人员11：ID
        self.procedure12_man_id = 0  # 人员12：ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = 0.0  # 对应第1制程工序工时
        self.procedure2_manhours = 0.0  # 对应第2制程工序工时
        self.procedure3_manhours = 0.0  # 对应第3制程工序工时
        self.procedure4_manhours = 0.0  # 对应第4制程工序工时
        self.procedure5_manhours = 0.0  # 对应第5制程工序工时
        self.procedure6_manhours = 0.0  # 对应第6制程工序工时
        self.procedure7_manhours = 0.0  # 对应第7制程工序工时
        self.procedure8_manhours = 0.0  # 对应第8制程工序工时
        self.procedure9_manhours = 0.0  # 对应第9制程工序工时
        self.procedure10_manhours = 0.0  # 对应第10制程工序工时
        self.procedure11_manhours = 0.0  # 对应第11制程工序工时
        self.procedure12_manhours = 0.0  # 对应第12制程工序工时
        self.update_time = None  # 用该日期初始化，说明该人是空闲的
        self.jhwg = None        # 计划完工时间
        self.overtime_hours = 0.0   # 超过的最后的时间，即：加班工时
        self.planlog_id = 0     # planlogID 更新定位
        self.workorder_id = 0   # 工单ID 更新定位
    def clear(self):
        self.procedure1_man_id = 0  # 人员1：ID
        self.procedure2_man_id = 0  # 人员2：ID
        self.procedure3_man_id = 0  # 人员3：ID
        self.procedure4_man_id = 0  # 人员4：ID
        self.procedure5_man_id = 0  # 人员5：ID
        self.procedure6_man_id = 0  # 人员6：ID
        self.procedure7_man_id = 0  # 人员7：ID
        self.procedure8_man_id = 0  # 人员8：ID
        self.procedure9_man_id = 0  # 人员9：ID
        self.procedure10_man_id = 0  # 人员10：ID
        self.procedure11_man_id = 0  # 人员11：ID
        self.procedure12_man_id = 0  # 人员12：ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = 0.0  # 对应第1制程工序工时
        self.procedure2_manhours = 0.0  # 对应第2制程工序工时
        self.procedure3_manhours = 0.0  # 对应第3制程工序工时
        self.procedure4_manhours = 0.0  # 对应第4制程工序工时
        self.procedure5_manhours = 0.0  # 对应第5制程工序工时
        self.procedure6_manhours = 0.0  # 对应第6制程工序工时
        self.procedure7_manhours = 0.0  # 对应第7制程工序工时
        self.procedure8_manhours = 0.0  # 对应第8制程工序工时
        self.procedure9_manhours = 0.0  # 对应第9制程工序工时
        self.procedure10_manhours = 0.0  # 对应第10制程工序工时
        self.procedure11_manhours = 0.0  # 对应第11制程工序工时
        self.procedure12_manhours = 0.0  # 对应第12制程工序工时
        self.update_time = None  # 用该日期初始化，说明该人是空闲的
        self.jhwg = None        # 计划完工时间
        self.overtime_hours = 0.0   # 超过的最后的时间，即：加班工时
        self.planlog_id = 0     # planlogID 更新定位
        self.workorder_id = 0   # 工单ID 更新定位
    def to_list(self):
        return [self.procedure1_man_id, self.procedure2_man_id, self.procedure3_man_id, self.procedure4_man_id,
                self.procedure5_man_id, self.procedure6_man_id, self.procedure7_man_id, self.procedure8_man_id,
                self.procedure9_man_id, self.procedure10_man_id, self.procedure11_man_id, self.procedure12_man_id,
                datetime_toString(self.procedure1_startdate), datetime_toString(self.procedure2_startdate),
                datetime_toString(self.procedure3_startdate), datetime_toString(self.procedure4_startdate),
                datetime_toString(self.procedure5_startdate), datetime_toString(self.procedure6_startdate),
                datetime_toString(self.procedure7_startdate), datetime_toString(self.procedure8_startdate),
                datetime_toString(self.procedure9_startdate), datetime_toString(self.procedure10_startdate),
                datetime_toString(self.procedure11_startdate), datetime_toString(self.procedure12_startdate),
                datetime_toString(self.procedure1_finishdate), datetime_toString(self.procedure2_finishdate),
                datetime_toString(self.procedure3_finishdate), datetime_toString(self.procedure4_finishdate),
                datetime_toString(self.procedure5_finishdate), datetime_toString(self.procedure6_finishdate),
                datetime_toString(self.procedure7_finishdate), datetime_toString(self.procedure8_finishdate),
                datetime_toString(self.procedure9_finishdate), datetime_toString(self.procedure10_finishdate),
                datetime_toString(self.procedure11_finishdate), datetime_toString(self.procedure12_finishdate),
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                datetime_toString(self.update_time), datetime_toString(self.jhwg),self.overtime_hours, self.planlog_id, self.workorder_id]  # 更新的datetime要转成str格式
    def __list__(self):
        return [self.procedure1_man_id, self.procedure2_man_id, self.procedure3_man_id, self.procedure4_man_id,
                self.procedure5_man_id, self.procedure6_man_id, self.procedure7_man_id, self.procedure8_man_id,
                self.procedure9_man_id, self.procedure10_man_id, self.procedure11_man_id, self.procedure12_man_id,
                datetime_toString(self.procedure1_startdate), datetime_toString(self.procedure2_startdate),
                datetime_toString(self.procedure3_startdate), datetime_toString(self.procedure4_startdate),
                datetime_toString(self.procedure5_startdate), datetime_toString(self.procedure6_startdate),
                datetime_toString(self.procedure7_startdate), datetime_toString(self.procedure8_startdate),
                datetime_toString(self.procedure9_startdate), datetime_toString(self.procedure10_startdate),
                datetime_toString(self.procedure11_startdate), datetime_toString(self.procedure12_startdate),
                datetime_toString(self.procedure1_finishdate), datetime_toString(self.procedure2_finishdate),
                datetime_toString(self.procedure3_finishdate), datetime_toString(self.procedure4_finishdate),
                datetime_toString(self.procedure5_finishdate), datetime_toString(self.procedure6_finishdate),
                datetime_toString(self.procedure7_finishdate), datetime_toString(self.procedure8_finishdate),
                datetime_toString(self.procedure9_finishdate), datetime_toString(self.procedure10_finishdate),
                datetime_toString(self.procedure11_finishdate), datetime_toString(self.procedure12_finishdate),
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                datetime_toString(self.update_time), datetime_toString(self.jhwg),self.overtime_hours, self.planlog_id, self.workorder_id]  # 更新的datetime要转成str格式

# 插入fa_aps_planlog0类
class InsertPlanlog0Class:
    def __init__(self):
        self.workorder_id = 0  # 工单ID 更新定位
        self.procedure1_id = 0  # 制程1：ID
        self.procedure2_id = 0  # 制程2：ID
        self.procedure3_id = 0  # 制程3：ID
        self.procedure4_id = 0  # 制程4：ID
        self.procedure5_id = 0  # 制程5：ID
        self.procedure6_id = 0  # 制程6：ID
        self.procedure7_id = 0  # 制程7：ID
        self.procedure8_id = 0  # 制程8：ID
        self.procedure9_id = 0  # 制程9：ID
        self.procedure10_id = 0  # 制程10：ID
        self.procedure11_id = 0  # 制程11：ID
        self.procedure12_id = 0  # 制程12：ID
        self.procedure1_man_id = 0  # 人员1：ID
        self.procedure2_man_id = 0  # 人员2：ID
        self.procedure3_man_id = 0  # 人员3：ID
        self.procedure4_man_id = 0  # 人员4：ID
        self.procedure5_man_id = 0  # 人员5：ID
        self.procedure6_man_id = 0  # 人员6：ID
        self.procedure7_man_id = 0  # 人员7：ID
        self.procedure8_man_id = 0  # 人员8：ID
        self.procedure9_man_id = 0  # 人员9：ID
        self.procedure10_man_id = 0  # 人员10：ID
        self.procedure11_man_id = 0  # 人员11：ID
        self.procedure12_man_id = 0  # 人员12：ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = None  # 对应第1制程所需时长
        self.procedure2_manhours = None  # 对应第2制程所需时长
        self.procedure3_manhours = None  # 对应第3制程所需时长
        self.procedure4_manhours = None  # 对应第4制程所需时长
        self.procedure5_manhours = None  # 对应第5制程所需时长
        self.procedure6_manhours = None  # 对应第6制程所需时长
        self.procedure7_manhours = None  # 对应第7制程所需时长
        self.procedure8_manhours = None  # 对应第8制程所需时长
        self.procedure9_manhours = None  # 对应第9制程所需时长
        self.procedure10_manhours = None  # 对应第10制程所需时长
        self.procedure11_manhours = None  # 对应第11制程所需时长
        self.procedure12_manhours = None  # 对应第12制程所需时长
        self.procedure1_preparedate = 0.0  # 原料1备齐日
        self.procedure2_preparedate = 0.0  # 原料2备齐日
        self.procedure3_preparedate = 0.0  # 原料3备齐日
        self.procedure4_preparedate = 0.0  # 原料4备齐日
        self.procedure5_preparedate = 0.0  # 原料5备齐日
        self.procedure6_preparedate = 0.0  # 原料6备齐日
        self.procedure7_preparedate = 0.0  # 原料7备齐日
        self.procedure8_preparedate = 0.0  # 原料8备齐日
        self.procedure9_preparedate = 0.0  # 原料9备齐日
        self.procedure10_preparedate = 0.0  # 原料10备齐日
        self.procedure11_preparedate = 0.0  # 原料11备齐日
        self.procedure12_preparedate = 0.0  # 原料12备齐日
        self.workorder_finishdate = None  # 工单计划完成时间
        self.finishnum = None     # 实际完成制程数
        self.maxnum = None        # 最大的制程数
        self.create_time = None   # 创建时间
        self.update_time = None   # 用该日期初始化，说明该人是空闲的
        self.state = "未完成"     # 状态
        self.jhwg = None          # 计划完工时间
        self.overtime_hours = 0.0 # 超过的最后的时间，即：加班工时
        self.yjkg = None    # 预计开工
        self.switch = 0     # 排程开关
        self.sjwg = None    # 实际完工时间
        self.procedure1_mannum = 0  # 原料1备齐日
        self.procedure2_mannum = 0  # 原料2备齐日
        self.procedure3_mannum = 0  # 原料3备齐日
        self.procedure4_mannum = 0  # 原料4备齐日
        self.procedure5_mannum = 0  # 原料5备齐日
        self.procedure6_mannum = 0  # 原料6备齐日
        self.procedure7_mannum = 0  # 原料7备齐日
        self.procedure8_mannum = 0  # 原料8备齐日
        self.procedure9_mannum = 0  # 原料9备齐日
        self.procedure10_mannum = 0  # 原料10备齐日
        self.procedure11_mannum = 0  # 原料11备齐日
        self.procedure12_mannum = 0  # 原料12备齐日
        self.pcyqzl = '否'   # 排程逾期製令
    def clear(self):
        self.workorder_id = 0  # 工单ID 更新定位
        self.procedure1_id = 0  # 制程1：ID
        self.procedure2_id = 0  # 制程2：ID
        self.procedure3_id = 0  # 制程3：ID
        self.procedure4_id = 0  # 制程4：ID
        self.procedure5_id = 0  # 制程5：ID
        self.procedure6_id = 0  # 制程6：ID
        self.procedure7_id = 0  # 制程7：ID
        self.procedure8_id = 0  # 制程8：ID
        self.procedure9_id = 0  # 制程9：ID
        self.procedure10_id = 0  # 制程10：ID
        self.procedure11_id = 0  # 制程11：ID
        self.procedure12_id = 0  # 制程12：ID
        self.procedure1_man_id = 0  # 人员1：ID
        self.procedure2_man_id = 0  # 人员2：ID
        self.procedure3_man_id = 0  # 人员3：ID
        self.procedure4_man_id = 0  # 人员4：ID
        self.procedure5_man_id = 0  # 人员5：ID
        self.procedure6_man_id = 0  # 人员6：ID
        self.procedure7_man_id = 0  # 人员7：ID
        self.procedure8_man_id = 0  # 人员8：ID
        self.procedure9_man_id = 0  # 人员9：ID
        self.procedure10_man_id = 0  # 人员10：ID
        self.procedure11_man_id = 0  # 人员11：ID
        self.procedure12_man_id = 0  # 人员12：ID
        self.procedure1_startdate = None  # 对应第1制程计划开始时间
        self.procedure2_startdate = None  # 对应第2制程计划开始时间
        self.procedure3_startdate = None  # 对应第3制程计划开始时间
        self.procedure4_startdate = None  # 对应第4制程计划开始时间
        self.procedure5_startdate = None  # 对应第5制程计划开始时间
        self.procedure6_startdate = None  # 对应第6制程计划开始时间
        self.procedure7_startdate = None  # 对应第7制程计划开始时间
        self.procedure8_startdate = None  # 对应第8制程计划开始时间
        self.procedure9_startdate = None  # 对应第9制程计划开始时间
        self.procedure10_startdate = None  # 对应第10制程计划开始时间
        self.procedure11_startdate = None  # 对应第11制程计划开始时间
        self.procedure12_startdate = None  # 对应第12制程计划开始时间
        self.procedure1_finishdate = None  # 对应第1制程计划结束时间
        self.procedure2_finishdate = None  # 对应第2制程计划结束时间
        self.procedure3_finishdate = None  # 对应第3制程计划结束时间
        self.procedure4_finishdate = None  # 对应第4制程计划结束时间
        self.procedure5_finishdate = None  # 对应第5制程计划结束时间
        self.procedure6_finishdate = None  # 对应第6制程计划结束时间
        self.procedure7_finishdate = None  # 对应第7制程计划结束时间
        self.procedure8_finishdate = None  # 对应第8制程计划结束时间
        self.procedure9_finishdate = None  # 对应第9制程计划结束时间
        self.procedure10_finishdate = None  # 对应第10制程计划结束时间
        self.procedure11_finishdate = None  # 对应第11制程计划结束时间
        self.procedure12_finishdate = None  # 对应第12制程计划结束时间
        self.procedure1_manhours = None  # 对应第1制程所需时长
        self.procedure2_manhours = None  # 对应第2制程所需时长
        self.procedure3_manhours = None  # 对应第3制程所需时长
        self.procedure4_manhours = None  # 对应第4制程所需时长
        self.procedure5_manhours = None  # 对应第5制程所需时长
        self.procedure6_manhours = None  # 对应第6制程所需时长
        self.procedure7_manhours = None  # 对应第7制程所需时长
        self.procedure8_manhours = None  # 对应第8制程所需时长
        self.procedure9_manhours = None  # 对应第9制程所需时长
        self.procedure10_manhours = None  # 对应第10制程所需时长
        self.procedure11_manhours = None  # 对应第11制程所需时长
        self.procedure12_manhours = None  # 对应第12制程所需时长
        self.procedure1_preparedate = 0.0  # 原料1备齐日
        self.procedure2_preparedate = 0.0  # 原料2备齐日
        self.procedure3_preparedate = 0.0  # 原料3备齐日
        self.procedure4_preparedate = 0.0  # 原料4备齐日
        self.procedure5_preparedate = 0.0  # 原料5备齐日
        self.procedure6_preparedate = 0.0  # 原料6备齐日
        self.procedure7_preparedate = 0.0  # 原料7备齐日
        self.procedure8_preparedate = 0.0  # 原料8备齐日
        self.procedure9_preparedate = 0.0  # 原料9备齐日
        self.procedure10_preparedate = 0.0  # 原料10备齐日
        self.procedure11_preparedate = 0.0  # 原料11备齐日
        self.procedure12_preparedate = 0.0  # 原料12备齐日
        self.workorder_finishdate = None  # 工单计划完成时间
        self.finishnum = None     # 实际完成制程数
        self.maxnum = None        # 最大的制程数
        self.create_time = None   # 创建时间
        self.update_time = None   # 用该日期初始化，说明该人是空闲的
        self.state = "未完成"     # 状态
        self.jhwg = None          # 计划完工时间
        self.overtime_hours = 0.0 # 超过的最后的时间，即：加班工时
        self.yjkg = None    # 预计开工
        self.switch = 0     # 排程开关
        self.sjwg = None    # 实际完工时间
        self.procedure1_mannum = 0  # 原料1备齐日
        self.procedure2_mannum = 0  # 原料2备齐日
        self.procedure3_mannum = 0  # 原料3备齐日
        self.procedure4_mannum = 0  # 原料4备齐日
        self.procedure5_mannum = 0  # 原料5备齐日
        self.procedure6_mannum = 0  # 原料6备齐日
        self.procedure7_mannum = 0  # 原料7备齐日
        self.procedure8_mannum = 0  # 原料8备齐日
        self.procedure9_mannum = 0  # 原料9备齐日
        self.procedure10_mannum = 0  # 原料10备齐日
        self.procedure11_mannum = 0  # 原料11备齐日
        self.procedure12_mannum = 0  # 原料12备齐日
        self.pcyqzl = '否'   # 排程逾期製令
    def to_list(self):
        return [self.workorder_id,
                self.procedure1_id, self.procedure2_id, self.procedure3_id, self.procedure4_id,
                self.procedure5_id, self.procedure6_id, self.procedure7_id, self.procedure8_id,
                self.procedure9_id, self.procedure10_id, self.procedure11_id, self.procedure12_id,
                self.procedure1_man_id, self.procedure2_man_id, self.procedure3_man_id, self.procedure4_man_id,
                self.procedure5_man_id, self.procedure6_man_id, self.procedure7_man_id, self.procedure8_man_id,
                self.procedure9_man_id, self.procedure10_man_id, self.procedure11_man_id, self.procedure12_man_id,
                self.procedure1_startdate, self.procedure2_startdate,self.procedure3_startdate, self.procedure4_startdate,
                self.procedure5_startdate, self.procedure6_startdate,self.procedure7_startdate, self.procedure8_startdate,
                self.procedure9_startdate, self.procedure10_startdate, self.procedure11_startdate, self.procedure12_startdate,
                self.procedure1_finishdate, self.procedure2_finishdate,self.procedure3_finishdate, self.procedure4_finishdate,
                self.procedure5_finishdate, self.procedure6_finishdate,self.procedure7_finishdate, self.procedure8_finishdate,
                self.procedure9_finishdate, self.procedure10_finishdate, self.procedure11_finishdate, self.procedure12_finishdate,
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                self.procedure1_preparedate, self.procedure2_preparedate, self.procedure3_preparedate, self.procedure4_preparedate,
                self.procedure5_preparedate, self.procedure6_preparedate, self.procedure7_preparedate, self.procedure8_preparedate,
                self.procedure9_preparedate, self.procedure10_preparedate, self.procedure11_preparedate, self.procedure12_preparedate,
                self.procedure1_mannum, self.procedure2_mannum, self.procedure3_mannum,
                self.procedure4_mannum, self.procedure5_mannum, self.procedure6_mannum,
                self.procedure7_mannum, self.procedure8_mannum, self.procedure9_mannum,
                self.procedure10_mannum, self.procedure11_mannum, self.procedure12_mannum,
                self.workorder_finishdate, self.finishnum, self.maxnum, self.create_time, self.update_time,
                self.state, self.jhwg, self.overtime_hours, self.yjkg, self.switch, self.sjwg, self.pcyqzl]
    def __list__(self):
        return [self.workorder_id,
                self.procedure1_id, self.procedure2_id, self.procedure3_id, self.procedure4_id,
                self.procedure5_id, self.procedure6_id, self.procedure7_id, self.procedure8_id,
                self.procedure9_id, self.procedure10_id, self.procedure11_id, self.procedure12_id,
                self.procedure1_man_id, self.procedure2_man_id, self.procedure3_man_id, self.procedure4_man_id,
                self.procedure5_man_id, self.procedure6_man_id, self.procedure7_man_id, self.procedure8_man_id,
                self.procedure9_man_id, self.procedure10_man_id, self.procedure11_man_id, self.procedure12_man_id,
                self.procedure1_startdate, self.procedure2_startdate,self.procedure3_startdate, self.procedure4_startdate,
                self.procedure5_startdate, self.procedure6_startdate,self.procedure7_startdate, self.procedure8_startdate,
                self.procedure9_startdate, self.procedure10_startdate, self.procedure11_startdate, self.procedure12_startdate,
                self.procedure1_finishdate, self.procedure2_finishdate,self.procedure3_finishdate, self.procedure4_finishdate,
                self.procedure5_finishdate, self.procedure6_finishdate,self.procedure7_finishdate, self.procedure8_finishdate,
                self.procedure9_finishdate, self.procedure10_finishdate, self.procedure11_finishdate, self.procedure12_finishdate,
                self.procedure1_manhours, self.procedure2_manhours, self.procedure3_manhours, self.procedure4_manhours,
                self.procedure5_manhours, self.procedure6_manhours, self.procedure7_manhours, self.procedure8_manhours,
                self.procedure9_manhours, self.procedure10_manhours, self.procedure11_manhours, self.procedure12_manhours,
                self.procedure1_preparedate, self.procedure2_preparedate, self.procedure3_preparedate, self.procedure4_preparedate,
                self.procedure5_preparedate, self.procedure6_preparedate, self.procedure7_preparedate, self.procedure8_preparedate,
                self.procedure9_preparedate, self.procedure10_preparedate, self.procedure11_preparedate, self.procedure12_preparedate,
                self.procedure1_mannum, self.procedure2_mannum, self.procedure3_mannum,
                self.procedure4_mannum, self.procedure5_mannum, self.procedure6_mannum,
                self.procedure7_mannum, self.procedure8_mannum, self.procedure9_mannum,
                self.procedure10_mannum, self.procedure11_mannum, self.procedure12_mannum,
                self.workorder_finishdate, self.finishnum, self.maxnum, self.create_time, self.update_time,
                self.state, self.jhwg, self.overtime_hours, self.yjkg, self.switch, self.sjwg, self.pcyqzl]

# 插入fa_aps_znpa类
class InsertZNPAClass:
    def __init__(self):
        self.name = 0   # 工单名称
        self.workorder_finishdate_new = None  # 新-需求完工时间
        self.workorder_finishdate = None      # 旧-需求完工时间
    def clear(self):
        self.name = 0   # 工单名称
        self.workorder_finishdate_new = None  # 新-需求完工时间
        self.workorder_finishdate = None      # 旧-需求完工时间
    def to_list(self):
        return [self.name, self.workorder_finishdate_new, self.workorder_finishdate]
    def __list__(self):
        return [self.name, self.workorder_finishdate_new, self.workorder_finishdate]

# 更新fa_aps_znpa类
class UpdateZNPAClass:
    def __init__(self):
        self.workorder_finishdate_new = None  # 新-需求完工时间
        self.id = 0     # 工单ID
    def clear(self):
        self.workorder_finishdate_new = None  # 新-需求完工时间
        self.id = 0     # 工单ID
    def to_list(self):
        return [self.workorder_finishdate_new, self.id]
    def __list__(self):
        return [self.workorder_finishdate_new, self.id]

# 更新fa_aps_subplanlog表，可以更新也可以插入
class SubPlanlogClass:
    def __init__(self):
        self.man_id = ''  # 操作工ID
        self.startdate = None   # 工序开始时间
        self.finishdate = None  # 工序结束时间
        self.procedureX_manhours = 0.0  # 工序工时
        self.planlog_id = 0     # 对应fa_aps_planlog的id
        self.procedureX_id = 0  # 对应planlog中的工序procedure_ID

    def clear(self):
        self.man_id = ''  # 操作工ID
        self.startdate = None   # 工序开始时间
        self.finishdate = None  # 工序结束时间
        self.procedureX_manhours = 0.0  # 工序工时
        self.planlog_id = 0     # 对应fa_aps_planlog的id
        self.procedureX_id = 0  # 对应planlog中的工序procedure_ID

    def to_list(self):
        return [self.man_id, datetime_toString(self.startdate), datetime_toString(self.finishdate),
                self.procedureX_manhours, self.planlog_id, self.procedureX_id]  # 更新的datetime要转成str格式

    def __list__(self):
        return [self.man_id, datetime_toString(self.startdate), datetime_toString(self.finishdate),
                self.procedureX_manhours, self.planlog_id, self.procedureX_id]  # 更新的datetime要转成str格式

# 记录所有已经排序好工单，排序规则是按最后必须要开始的工作时间，该时间是将预计完成时间减去该工单的所有工序的时间相加所得，并按从小到大的顺序排列
class SortedWorkorder:
    def __init__(self):
        self.planID = 0  # 该planlog的ID
        self.workorderID = 0  # 工单ID
        self.beginWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.endWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.finishnum = 0  # 已经完成的工序数
        self.maxnum = 0  # 该工单所有的工序数
        self.sumUnfinishedmanhours = 0  # 未完成的工序时间和
    def clear(self):
        self.planID = 0  # 该planlog的ID
        self.workorderID = 0  # 工单ID
        self.beginWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.endWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.finishnum = 0  # 已经完成的工序数
        self.maxnum = 0  # 该工单所有的工序数
        self.sumUnfinishedmanhours = 0  # 未完成的工序时间和
    def to_list(self):
        return [self.planID, self.workorderID, self.beginWorkTime, self.endWorkTime, self.finishnum, self.maxnum, self.sumUnfinishedmanhours]
    def __list__(self):
        return [self.planID, self.workorderID, self.beginWorkTime, self.endWorkTime, self.finishnum, self.maxnum, self.sumUnfinishedmanhours]

# 人员工作时间表，记录该所有人员安排时间段
class ManWorkingTimeClass:
    def __init__(self):
        self.manID = 0  # 负责改制程的人员的ID
        self.beginWorkTime = datetime.datetime.strptime('2012-01-01 00:00', '%Y-%m-%d %H:%M')  # 用该日期初始化，说明该人是空闲的
        self.endWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.ToNextWorkFreetime = -1  # 距离下个工作时段的空闲的时间间隔，默认-1代表后面都空闲
    def clear(self):
        self.manID = 0  # 负责改制程的人员的ID
        self.beginWorkTime = datetime.datetime.strptime('2012-01-01 00:00', '%Y-%m-%d %H:%M')  # 用该日期初始化，说明该人是空闲的
        self.endWorkTime = None  # 用该日期初始化，说明该人是空闲的
        self.ToNextWorkFreetime = -1  # 距离下个工作时段的空闲的时间间隔，默认-1代表后面都空闲
    def to_list(self):
        return [self.manID, self.beginWorkTime, self.endWorkTime, self.ToNextWorkFreetime]
    def __list__(self):
        return [self.manID, self.beginWorkTime, self.endWorkTime, self.ToNextWorkFreetime]

# 技能能力值计算方式：选人原则是能力值越低越优先选择。
class DevicetypeID2ManIDClass:
    def __init__(self):
        self.DevicetypeID = 0   # 设备ID
        self.manID = 0          # 能做该制程的人员ID
        self.ability = 100        # 技能能力值
    def clear(self):
        self.DevicetypeID = 0  # 设备ID
        self.manID = 0  # 能做该制程的人员ID
        self.ability = 100        # 技能能力值
    def to_list(self):
        return [self.DevicetypeID, self.manID, self.ability]
    def __list__(self):
        return [self.DevicetypeID, self.manID, self.ability]

# 判断一个时间段内跨越几周
def CountOverWeeks(BeginDate, EndDate):
    nWeeks = 0
    VarDate = BeginDate
    for i in range((EndDate-BeginDate).days):
        whatday = VarDate.weekday()
        if whatday == 5: # 周六
            nWeeks += 1
        delta = datetime.timedelta(days=1)
        VarDate += delta

    return nWeeks

# 调整日期时间从休息日调整到工作日时间内
# 输入参数：InputStarttime为datetime格式
# 输入参数：AdjustDirection为正负，代表加减
def AdjustRestToWorkdatetime(InputStarttime, AdjustDirection):
    # 取结束日期是星期几？
    # 0: '星期一' ... 4: '星期五', 5: '星期六', 6: '星期天'
    nWeekDay_End = InputStarttime.weekday()
    if nWeekDay_End > 4:  # 在周末
        # 再加上周末的天数
        if AdjustDirection > 0: # 向前调整为下周一
            delta = datetime.timedelta(days=7 - nWeekDay_End)
        else:   # 向前调整为上周五
            delta = datetime.timedelta(days=nWeekDay_End - 4)
            delta *= -1
        InputStarttime += delta
    return InputStarttime

# 函数功能：调整输入的datetime时间为工作时间，如果InputDelta为0，代表是开始的时间点，要调整为开始时间
# 要求如下：
# 1、输入的开始时间点一定要在工作时间段，因为每个时间点都通过了该函数，故该点已经满足
# 2、输入参数Input_StartDateTime是datetime格式
# 3、输入参数InputDelta是时间段，float格式，单位是小时
# 4、输入参数manID是对某个人的时间做调整，如果是0对所有人都有效
# 5、输入参数AllVacationContents是所有人有效的休息时间段
# 6、输入参数AllOvertimeContents是所有人有效的加班时间段
def AdjustToWorkingHours(Input_StartDateTime, InputDelta, manID, AllOvertimeContents):
    # global g_countTest1
    # g_countTest1 += 1
    # if g_countTest1 >= 3106:
    #     pass
    RetDateTime = Input_StartDateTime  # 返回值，是datetime类型
    if InputDelta < 0:  # 时间往回退，其他情况是向前
        MidNightDatetime = datetime.datetime.strptime(str(Input_StartDateTime.date()) + '00:00:00', '%Y-%m-%d%H:%M:%S')
        if MidNightDatetime == Input_StartDateTime:  # 是午夜：YYYY-MM-DD 00:00:00，要调整为前一天的下班时间
            delta = datetime.timedelta(days=1)
            RetDateTime = RetDateTime - delta
            RetDateTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonEndWorktime, '%Y-%m-%d%H:%M')
            # 向前调整到工作时间段
            RetDateTime = AdjustRestToWorkdatetime(RetDateTime, -1)
            Input_StartDateTime = RetDateTime

    # 开始工作日的上午工作时间段
    BeginDayMorning_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningStartWorktime,
                                                            '%Y-%m-%d%H:%M')
    BeginDayMorning_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningEndWorktime,
                                                            '%Y-%m-%d%H:%M')
    # 开始工作日的下午工作时间段
    BeginDayAfternoon_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonStartWorktime,
                                                            '%Y-%m-%d%H:%M')
    BeginDayAfternoon_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonEndWorktime,
                                                            '%Y-%m-%d%H:%M')

    if InputDelta < 0:  # 时间往回退，其他情况是向前
        # 需要调整到达的时间
        InputDelta *= -1
        nWeeks = int(InputDelta / (g_PerWeekWorkingDays * g_PerDayWorkingTime))  # 时间间隔跨越几周？
        nRestHoursInOneWeek = InputDelta - nWeeks * (g_PerWeekWorkingDays * g_PerDayWorkingTime) # 在一周内还有几个小时
        # 以下调整时间，扣除整周和整天后，剩下的时间都是小于一天的工作时间，也就是8小时
        delta = datetime.timedelta(hours=nWeeks * 7 * 24 +
                                         int(nRestHoursInOneWeek / g_PerDayWorkingTime) * 24 +
                                         nRestHoursInOneWeek - int(nRestHoursInOneWeek / g_PerDayWorkingTime) * g_PerDayWorkingTime)
        RetDateTime1 = Input_StartDateTime - delta
        # 调整输入时间为正常工作日内
        RetDateTime = AdjustRestToWorkdatetime(RetDateTime1, -1)
        if RetDateTime1 != RetDateTime:
            # 0: '星期一' ... 4: '星期五', 5: '星期六', 6: '星期天'
            nWeekDay_End = RetDateTime1.weekday()
            if nWeekDay_End == 5:   # 特别处理多减1天，落在周六
                delta = datetime.timedelta(days=1)
                RetDateTime -= delta
        # 调整后的开始时间
        AdjustBeginDateTime = RetDateTime

        # 结束工作日的上午工作时间段
        EndDayMorning_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningStartWorktime,
                                                             '%Y-%m-%d%H:%M')
        EndDayMorning_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningEndWorktime,
                                                           '%Y-%m-%d%H:%M')
        # 开始工作日的下午工作时间段
        EndDayAfternoon_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonStartWorktime,
                                                               '%Y-%m-%d%H:%M')
        EndDayAfternoon_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonEndWorktime,
                                                             '%Y-%m-%d%H:%M')

        # 判断要扣除几个休息时间段
        # 刚输入的时间在上午工作时间段
        if Input_StartDateTime >= BeginDayMorning_StartTime and Input_StartDateTime <= BeginDayMorning_EndTime:
            # 也落在了上午时间段，不用处理。
            if AdjustBeginDateTime >= EndDayMorning_StartTime and AdjustBeginDateTime <= EndDayMorning_EndTime:
                pass
            # 只有可能落在了上午凌晨时间段，要减去晚上的时间，因为只减去了最多8个小时
            elif AdjustBeginDateTime < EndDayMorning_StartTime:
                delta = datetime.timedelta(hours=g_NightRestTime)
                AdjustBeginDateTime -= delta
                # 要再判断下新日期是否又落在了前一个工作日的中午时间段
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_AfternoonStartWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime < temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours = g_NoonRestTime)
                    AdjustBeginDateTime -= delta
        # 刚输入的时间在下午工作时间段
        else:
            # 也落在了下午时间段，不用处理。
            if AdjustBeginDateTime >= EndDayAfternoon_StartTime and AdjustBeginDateTime <= EndDayAfternoon_EndTime:
                pass
            # 落在了上午工作时间段或中午休息时间段，要减去中午休息时间段
            elif AdjustBeginDateTime < EndDayAfternoon_StartTime:
                delta = datetime.timedelta(hours=g_NoonRestTime)
                AdjustBeginDateTime -= delta
                # 要判断是否又落在了凌晨时间内
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_MorningStartWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime < temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours = g_NightRestTime)
                    AdjustBeginDateTime -= delta
            # 落在了上午凌晨时间段，要减去中午和晚上的休息时间
            elif AdjustBeginDateTime < EndDayMorning_StartTime:
                delta = datetime.timedelta(hours=g_NightRestTime + g_NoonRestTime)
                AdjustBeginDateTime -= delta
                # 要判断是否又落在了中午休息时间内
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_AfternoonStartWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime < temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours = g_NoonRestTime)
                    AdjustBeginDateTime -= delta
        # 向前调整到工作日内
        RetDateTime = AdjustRestToWorkdatetime(AdjustBeginDateTime, -1)
    elif InputDelta > 0:
        # 需要调整到达的时间，最大到周
        nWeeks = int(InputDelta / (g_PerWeekWorkingDays * g_PerDayWorkingTime))  # 时间间隔跨越几周？
        nRestHoursInOneWeek = InputDelta - nWeeks * (g_PerWeekWorkingDays * g_PerDayWorkingTime) # 在一周内还有几个小时
        # 以下调整时间，扣除整周和整天后，剩下的时间都是小于一天的工作时间，也就是8小时
        delta = datetime.timedelta(hours=nWeeks * 7 * 24 +
                                         int(nRestHoursInOneWeek / g_PerDayWorkingTime) * 24 +
                                         nRestHoursInOneWeek - int(nRestHoursInOneWeek / g_PerDayWorkingTime) * g_PerDayWorkingTime)
        RetDateTime1 = Input_StartDateTime + delta
        # 调整输入时间为正常工作日内
        RetDateTime = AdjustRestToWorkdatetime(RetDateTime1, 1)
        if RetDateTime1 != RetDateTime:
            # 0: '星期一' ... 4: '星期五', 5: '星期六', 6: '星期天'
            nWeekDay_End = RetDateTime1.weekday()
            if nWeekDay_End == 6:   # 特别处理多加1天，落在周天
                delta = datetime.timedelta(days=1)
                RetDateTime += delta
        # 调整后的开始时间
        AdjustBeginDateTime = RetDateTime

        # 结束工作日的上午工作时间段
        EndDayMorning_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningStartWorktime,
                                                             '%Y-%m-%d%H:%M')
        EndDayMorning_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_MorningEndWorktime,
                                                           '%Y-%m-%d%H:%M')
        # 开始工作日的下午工作时间段
        EndDayAfternoon_StartTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonStartWorktime,
                                                               '%Y-%m-%d%H:%M')
        EndDayAfternoon_EndTime = datetime.datetime.strptime(str(RetDateTime.date()) + g_AfternoonEndWorktime,
                                                             '%Y-%m-%d%H:%M')
        # 判断要扣除几个休息时间段
        # 刚输入的时间在上午工作时间段
        if Input_StartDateTime >= BeginDayMorning_StartTime and Input_StartDateTime <= BeginDayMorning_EndTime:
            # 落在了凌晨时间段
            if AdjustBeginDateTime < EndDayMorning_StartTime:
                delta = datetime.timedelta(hours = g_NightRestTime)
                AdjustBeginDateTime += delta
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_MorningEndWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime > temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours=g_NoonRestTime)
                    AdjustBeginDateTime += delta
            # 也落在了上午时间段，不用处理
            elif AdjustBeginDateTime >= EndDayMorning_StartTime and AdjustBeginDateTime <= EndDayMorning_EndTime:
                pass
            # 包含了中午休息时间段，就要加上
            elif AdjustBeginDateTime > EndDayMorning_EndTime and AdjustBeginDateTime <= EndDayAfternoon_EndTime:
                delta = datetime.timedelta(hours = g_NoonRestTime)
                AdjustBeginDateTime += delta
                # 要再判断下是否又落在了下个工作日的中午时间段或下午时间段，只有这一个可能
                temp_EndDayAfternoon_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_AfternoonEndWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime > temp_EndDayAfternoon_EndTime:
                    delta = datetime.timedelta(hours = g_NightRestTime)
                    AdjustBeginDateTime += delta
            elif AdjustBeginDateTime > EndDayAfternoon_EndTime:
                delta = datetime.timedelta(hours = g_NoonRestTime + g_NightRestTime)
                AdjustBeginDateTime += delta
                # 要再判断下是否又落在了下个工作日的中午时间段或下午时间段，只有这一个可能
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_MorningEndWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime > temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours = g_NoonRestTime)
                    AdjustBeginDateTime += delta
        # 刚输入的时间在下午工作时间段
        else:
            # 落在了凌晨时间段
            if AdjustBeginDateTime < EndDayAfternoon_StartTime:
                delta = datetime.timedelta(hours = g_NightRestTime)
                AdjustBeginDateTime += delta
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_MorningEndWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime > temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours=g_NoonRestTime)
                    AdjustBeginDateTime += delta
            # 也落在了下午时间段，不用处理
            elif AdjustBeginDateTime >= EndDayAfternoon_StartTime and AdjustBeginDateTime <= EndDayAfternoon_EndTime:
                pass
            # 落在了凌晨或上午时间段，要加上晚上时间段
            elif AdjustBeginDateTime > EndDayAfternoon_EndTime:
                delta = datetime.timedelta(hours = g_NightRestTime)
                AdjustBeginDateTime += delta
                temp_EndDayMorning_EndTime = datetime.datetime.strptime(str(AdjustBeginDateTime.date()) + g_MorningEndWorktime, '%Y-%m-%d%H:%M')
                if AdjustBeginDateTime > temp_EndDayMorning_EndTime:
                    delta = datetime.timedelta(hours=g_NoonRestTime)
                    AdjustBeginDateTime += delta
            # 落在了下午时间段或晚上时间段，不用考虑，因为时间差已经在8小时之内
            else:
               pass
        # 统一调整输入时间为正常工作日内
        RetDateTime = AdjustRestToWorkdatetime(AdjustBeginDateTime, 1)
    else:  # InputDelta==0的情况，初始时间确认
        if RetDateTime < BeginDayMorning_StartTime: # 在上班前，调整为上班时间点
            RetDateTime = BeginDayMorning_StartTime
        elif RetDateTime >= BeginDayAfternoon_EndTime: # 在下班后，调整为第二天上班时间点
            RetDateTime = BeginDayMorning_StartTime
            delta = datetime.timedelta(days=1)
            RetDateTime += delta
        elif RetDateTime >= BeginDayMorning_EndTime and RetDateTime < BeginDayAfternoon_StartTime:  # 在午休时间，调整为下午上班时间点
            RetDateTime = BeginDayAfternoon_StartTime
        # 统一调整输入时间为正常工作日内
        RetDateTime = AdjustRestToWorkdatetime(RetDateTime, 1)
    # TestDatetime = datetime.datetime.strptime(str(RetDateTime.date()) + '00:00:00', '%Y-%m-%d%H:%M:%S')
    # if TestDatetime == RetDateTime:
    #     pass
    # 最后返回调整后的时间
    return RetDateTime

# 取得所有人员的工作时间表，制程组成所有的人员：制程ID / 人员，同时也可以反查：人员 / 制程ID
# 区分出急单（距离开工时间相差1天的）、未完成工单、新工单
# 要注意未完成的工单，已经做好的工序的时间不能考虑在内
def GetSortedWordorderList(inputStartTime, AllPlanlogResult, AllVacationContents, AllOvertimeContents):
    strdatetime = inputStartTime.strftime("'%Y-%m-%d %H:%M'")  # 将datetime变成字符串
    # 先保存所有的人员ID
    OneSortedWorkorderList = SortedWorkorder()
    AllSortedWorkorderList = []
    for row in AllPlanlogResult:
        OneSortedWorkorderList.planID = row[0]  # planid
        OneSortedWorkorderList.workorderID = row[1]  # workorder_id
        # 开始时间点
        SumAllProcedureManhours = 0.0
        # 从未完成的工序开始
        # 43 + int(row[4])代表procedureN_manhours位置
        for i in range(43 + int(row[4]), 43 + int(row[5])):
            SumAllProcedureManhours += float(row[i])
        SumAllProcedureManhours *= -1  # 往回退的时间段
        if row[6] is None:  # 容错
            OneSortedWorkorderList.beginWorkTime = inputStartTime
            OneSortedWorkorderList.endWorkTime = AdjustToWorkingHours(inputStartTime,    # 预计完成的时间workorder_finishdate
                                                                        SumAllProcedureManhours * (-1),    # 还需要多少时间才能完成
                                                                        0,      # 人员ID
                                                                        AllOvertimeContents)  # 加班的时间
        else:
            OneSortedWorkorderList.beginWorkTime = AdjustToWorkingHours(row[6],    # 预计完成的时间workorder_finishdate
                                                                        SumAllProcedureManhours,    # 还需要多少时间才能完成
                                                                        0,      # 人员ID
                                                                        AllOvertimeContents)  # 加班的时间
            OneSortedWorkorderList.endWorkTime = row[6]  # 计划结束时间workorder_finishdate
        OneSortedWorkorderList.maxnum = int(row[5])  # 总的制程数
        OneSortedWorkorderList.finishnum = int(row[4])  # 已经完成的工序数
        OneSortedWorkorderList.sumUnfinishedmanhours = SumAllProcedureManhours*(-1)  # 未完成的工序之和
        # 最后转成列表 追加到类中
        AllSortedWorkorderList.append(OneSortedWorkorderList.to_list())

    # 列表排序
    AllSortedWorkorderList = sorted(AllSortedWorkorderList, key=lambda x: (x[3], x[0], x[1]))  # 按列表的第3列最迟开始的时间升序排序
    # 区分急单和未完成的工单
    AlartSortedWorkorderList = []  # 急单
    UnfinishedWorkorderList = []  # 未完成的工单
    NewWorkorderList = []  # 新工单
    AdjustStartTime = AdjustRestToWorkdatetime(inputStartTime, -1)  # 向前调整开始工作时间
    for row in AllSortedWorkorderList:
        if (row[2] - AdjustStartTime).days <= g_AlartWorkorder_DiffDays:  # 急单，暂定为1天之内
            AlartSortedWorkorderList.append(row)
            continue
        if row[4] > 0 and row[4] <> row[5]:  # 未完成的工单
            UnfinishedWorkorderList.append(row)
            continue
        else:
            NewWorkorderList.append(row)  # 新工单
    # 返回各个列表，总列表、急单（距离开工时间相差1天的）、未完成工单、新工单
    return (AllSortedWorkorderList, AlartSortedWorkorderList, UnfinishedWorkorderList, NewWorkorderList)

# 非常重要，要动态调整能力值
# 最空闲超过0.5小时（暂定），就要安排法
# 每次都将同一个devicetype里，所有能做给devicetype，最低的那个人如果与最高的那个人的空闲时间超过2小时（暂定）,
# 就将其提到最高（只要将原来最高的能力值基础上加1即可），以便下次安排他排工
def DynamicAbility(AllManWorkingArray_O, AllDevicetypeID2ManIDArray):
    if len(AllManWorkingArray_O) == 0 or len(AllDevicetypeID2ManIDArray) == 0:
        return AllDevicetypeID2ManIDArray
    # 先按序
    AllDevicetypeID2ManIDArray_copy = sorted(AllDevicetypeID2ManIDArray, key=lambda x: (x[0], x[2], x[1]))
    AllManWorkingArray_O_copy = sorted(AllManWorkingArray_O, key=lambda x: (x[0], x[2], x[3]))

    CurrentDevicetypeID = AllDevicetypeID2ManIDArray_copy[0][0] # 第一个devicetypeID 初始化
    CurrentDateTime = AllManWorkingArray_O_copy[0][3] # 第一个人时间 初始化

    nCurrentDevicetypeFirstLine = 0 # 需要记录当前第一个devicetype位置，为了后面从此开始，计算能力值
    for i in range(len(AllDevicetypeID2ManIDArray_copy)):
        if AllDevicetypeID2ManIDArray_copy[i][0] <> CurrentDevicetypeID:  # 到了下一个devicetypeID
            # 判断AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][1]这个人和AllDevicetypeID2ManIDArray_copy[i-1][1]这个人的时间差
            BeforeDatetime = AllManWorkingArray_O_copy[0][2]
            EndDatetime = AllManWorkingArray_O_copy[0][2]
            for m in range(len(AllManWorkingArray_O_copy)):
                if AllManWorkingArray_O_copy[m][0] == AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][1]:
                    BeforeDatetime = AllManWorkingArray_O_copy[m][2]
                if AllManWorkingArray_O_copy[m][0] == AllDevicetypeID2ManIDArray_copy[i-1][1]:
                    EndDatetime = AllManWorkingArray_O_copy[m][2]
            if EndDatetime > BeforeDatetime:
                # 相差1天按8小时工作时间
                deltaHours = (EndDatetime - BeforeDatetime).days * 8 + (EndDatetime - BeforeDatetime).seconds / 3600
                if deltaHours >= 0.5:  # 满足条件差了0.5小时
                    AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] = AllDevicetypeID2ManIDArray_copy[i - 1][2] + 1
                    # if(g_DeviceTypeID2ab_disc.has_key(AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0])):
                    #     if g_DeviceTypeID2ab_disc[AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0]] != 0:
                    #         AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] += g_DeviceTypeID2ab_disc[
                    #             AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0]]
                    #     else:
                    #         AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] += 1
            # 当前的人员ID
            CurrentDevicetypeID = AllDevicetypeID2ManIDArray_copy[i][0]
            nCurrentDevicetypeFirstLine = i  # 需要记录当前人员的第一个位置，为了后面从此开始，计算能力值
    # 最后一个人，计算公式里的分母：即【该技能会的人数】。
    # 同一个人的能力值公式里，分子都是相同的，只有分母不同
    # 依次填写当前该人CurrentManID的所有会的技能的能力值
    BeforeDatetime = AllManWorkingArray_O_copy[0][2]
    EndDatetime = AllManWorkingArray_O_copy[0][2]
    for m in range(len(AllManWorkingArray_O_copy)):
        if AllManWorkingArray_O_copy[m][0] == AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][1]:
            BeforeDatetime = AllManWorkingArray_O_copy[m][2]
        if AllManWorkingArray_O_copy[m][0] == AllDevicetypeID2ManIDArray_copy[i - 1][1]:
            EndDatetime = AllManWorkingArray_O_copy[m][2]
    if EndDatetime > BeforeDatetime:
        # 相差1天按8小时工作时间
        deltaHours = (EndDatetime - BeforeDatetime).days * 8 + (EndDatetime - BeforeDatetime).seconds / 3600
        if deltaHours >= 2:  # 满足条件差了2小时
            AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] = AllDevicetypeID2ManIDArray_copy[i-1][2] + 1
            # if (g_DeviceTypeID2ab_disc.has_key(AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0])):
            #     if g_DeviceTypeID2ab_disc[AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0]] != 0:
            #         AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] += g_DeviceTypeID2ab_disc[
            #             AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][0]]
            #     else:
            #         AllDevicetypeID2ManIDArray_copy[nCurrentDevicetypeFirstLine][2] += 1

    AllDevicetypeID2ManIDArray_copy = sorted(AllDevicetypeID2ManIDArray_copy, key=lambda x: (x[0], x[1], x[2]))  # 恢复排序
    return AllDevicetypeID2ManIDArray_copy

# 列表排序，结束的时间更重要，要排在开始时间的前面，并取得当前与下个工作空闲的时间段
def GetSortedAllManWorkingArrayAndToNextWorkFreetime(AllManWorkingArray):
    # global g_countTest
    # 列表排序，结束的时间更重要，要排在开始时间的前面
    AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[2], x[1], x[3]))
    # 并把其他距离下个工作时段的空闲时长计算出来，因为已经按manid、结束时间和开始时间排好序了，故如果是同一个人可以用后项减去前项
    i = 1   # 从1开始
    # g_countTest += 1
    # if g_countTest == 842:
    #     pass
    while i < len(AllManWorkingArray):
        if AllManWorkingArray[i - 1][0] == AllManWorkingArray[i][0]:  # 是同一个人，且不是追加的人
            # 更新前项的空闲时间段：后项的开始时间段 - 前项的结束时间段 单位是小时
            pre2nexttime_delta = (datetime_toTimestamp(AllManWorkingArray[i][1]) - \
                                            datetime_toTimestamp(AllManWorkingArray[i - 1][2])) / 3600.0
            # 合并1：俩段时间相连了，合并到前一项，并删除后项
            if pre2nexttime_delta < 0.09:   # 小于0.9小时=5.4分钟，就合并
                AllManWorkingArray[i - 1][2] = AllManWorkingArray[i][2]
                AllManWorkingArray[i - 1][3] = AllManWorkingArray[i][3]
                del AllManWorkingArray[i]
                continue

            # 合并2：还要判断是不是中间休息的衔接时间，如：前一个结束是中午11:30，和下一个段开始的时间13:00就是同一个时间点
            delta = datetime.timedelta(hours=g_NoonRestTime)
            tempDateTime = AllManWorkingArray[i - 1][2] + delta
            if tempDateTime == AllManWorkingArray[i][1]:
                AllManWorkingArray[i - 1][2] = AllManWorkingArray[i][2]
                AllManWorkingArray[i - 1][3] = AllManWorkingArray[i][3]
                del AllManWorkingArray[i]
                continue

            # 合并3：还要判断是不是晚上休息的衔接时间，如：前一个结束是下班18:00，和下一个段开始的时间早上8:30就是同一个时间点
            delta = datetime.timedelta(hours=g_NightRestTime)
            tempDateTime = AllManWorkingArray[i - 1][2] + delta
            if tempDateTime == AllManWorkingArray[i][1]:
                AllManWorkingArray[i - 1][2] = AllManWorkingArray[i][2]
                AllManWorkingArray[i - 1][3] = AllManWorkingArray[i][3]
                del AllManWorkingArray[i]
                continue

            # 开始工作日的上午工作时间段
            # pre_StartTime = datetime.datetime.strptime(str(AllManWorkingArray[i - 1][1].date()) + g_MorningStartWorktime,
            #                                                        '%Y-%m-%d%H:%M')
            pre_EndTime = datetime.datetime.strptime(str(AllManWorkingArray[i - 1][2].date()) + g_MorningEndWorktime,
                                                                 '%Y-%m-%d%H:%M')
            # 开始工作日的下午工作时间段
            next_StartTime = datetime.datetime.strptime(str(AllManWorkingArray[i][1].date()) + g_AfternoonStartWorktime,
                                                                     '%Y-%m-%d%H:%M')
            # next_EndTime = datetime.datetime.strptime(str(AllManWorkingArray[i][2].date()) + g_AfternoonEndWorktime,
            #                                                         '%Y-%m-%d%H:%M')

            # 是不是周五与周一相衔接
            # 合并4：0: '星期一' ... 4: '星期五', 5: '星期六', 6: '星期天'
            nWeekDay_End = AllManWorkingArray[i - 1][2].weekday()
            delta = datetime.timedelta(hours=2*24 + g_NightRestTime)
            # 周五的下班时间点和下周一的上班时间点，应该合并
            if nWeekDay_End == 4 and AllManWorkingArray[i - 1][2] + delta == AllManWorkingArray[i][1]:
                AllManWorkingArray[i - 1][2] = AllManWorkingArray[i][2]
                AllManWorkingArray[i - 1][3] = AllManWorkingArray[i][3]
                del AllManWorkingArray[i]
                continue

            # 时间差计算：跨周末的时间差要重新计算，要减去周末的时间差，就是48小时(2天)+1晚(周末的晚上)，从周五下班到下周一上班时间段
            # 重新计算AllManWorkingArray[i - 1][3]的值
            AllManWorkingArray[i - 1][3] = pre2nexttime_delta
            nSpanHowmuchWeeks = CountOverWeeks(AllManWorkingArray[i - 1][2], AllManWorkingArray[i][1])
            # 先减掉周末的时间
            if nSpanHowmuchWeeks > 0:   # 有跨越周末
                nhours = nSpanHowmuchWeeks * 48 # 2天
                AllManWorkingArray[i - 1][3] = pre2nexttime_delta - nhours
            # 再判断要扣除的周一到周五的中午和晚上的休息时间(不包括周5下班到周1上班的时间，因为前面已经减过了)
            ndays = (AllManWorkingArray[i][1]-AllManWorkingArray[i - 1][2]).days - nSpanHowmuchWeeks*2  # 周末是2天，已经减过了
            nhours = (AllManWorkingArray[i][1]-AllManWorkingArray[i - 1][2]).seconds/3600.0
            # 更新前项的空闲时间段：要扣除一整天中，休息的时间（中午和晚上的休息时间和），单位是小时
            AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - ndays * (g_NoonRestTime + g_NightRestTime)
            if nhours > 0: # 不够一整天
                if nhours < 8:  # 都在同一天，只有一个可能
                    if AllManWorkingArray[i - 1][2] <= pre_EndTime and AllManWorkingArray[i][1] >= next_StartTime:  # 前一段在上午 并且 后一段在下午，其他情况不可能
                        AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - g_NoonRestTime
                else: # 不在同一天，但在相邻的2天，不够一整天
                    if AllManWorkingArray[i - 1][2] <= pre_EndTime and AllManWorkingArray[i][1] < next_StartTime:  # 前一段在上午 并且 后一段也在上午
                        AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - g_NoonRestTime - g_NightRestTime   # 扣掉一个晚上和中午休息时间
                    #elif AllManWorkingArray[i - 1][2] <= pre_EndTime and AllManWorkingArray[i][1] >= next_StartTime:  # 前一段在上午 并且 后一段在下午：不可能，因为已经超过24小时了
                    #    AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - g_NoonRestTime - g_NightRestTime
                    elif AllManWorkingArray[i - 1][2] > pre_EndTime and AllManWorkingArray[i][1] >= next_StartTime:  # 前一段在下午 并且 后一段也在下午
                        AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - g_NoonRestTime - g_NightRestTime   # 扣掉一个晚上和中午休息时间
                    elif AllManWorkingArray[i - 1][2] > pre_EndTime and AllManWorkingArray[i][1] < next_StartTime:  # 前一段在下午 并且 后一段在上午
                        AllManWorkingArray[i - 1][3] = AllManWorkingArray[i - 1][3] - g_NightRestTime   # 扣掉一个晚上休息时间
            # test
            # if AllManWorkingArray[i - 1][3] < 0:
            #     pass
        # 自变量增加
        i += 1

    # 有更新，列表排序，结束的时间更重要，要排在开始时间的前面，最晚结束的时间排在前面，如果中间没有空闲的时间，就按最晚空闲的时间算
    AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[2], x[1], x[3]), reverse=True)
    return (AllManWorkingArray)

# 计算人员的能力值
# 技能能力值计算方式：选人原则是能力值越高越优先选择。
# 1、能力值的范围为【0-100】值越大，表明该人在该技能上，能力越强
# 2、能力大小对比是对应同一个技能，不同人进行对比
# 3、能力值编写规则：
# 3.1 计算公式是：[100 - A1(总的人数 - 会的人数) - ... An(总的人数 - 会的人数)]/该技能会的人数
# 3.2 首先要看这个人会几项技能技能An，会几项，就用100减去几项
# 3.3 计算每项An的值，即：总的人数 - 会的人数
# 3.4 最后用减去的值 除以 该技能会的人数，就得到该人的能力值
# 例如：
#               M1                                      M2                              M3
# A1(值)       x(100/3)                               x(97/3)                         x(99/3)
# A2(值)                                              x(97/2)                         x(99/2)
# A3(值)                                              x(97/1)
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 公式  [100-A1(3人-3人)]/3人    [100-A1(3人-3人)-A2(3人-2人)-A3(3人-1人)]/3人   [100-A1(3人-3人)-A2(3人-2人)]/3人
# 公式                           [100-A1(3人-3人)-A2(3人-2人)-A3(3人-1人)]/2人   [100-A1(3人-3人)-A2(3人-2人)]/2人
# 公式                           [100-A1(3人-3人)-A2(3人-2人)-A3(3人-1人)]/1人
# 添加新规则：
# 1、为了均衡排程，统计每个制程即devicetypeID(procedureIDn)在所有要排程的工单里有多少？假设为：a
# 2、然后统计该制程，有几个可以做？假设为：b。也就是说，这个制程要这几个人来分配。b目前太小，就放大倍数，先放大5倍：b=b*5
# 3、最后 不是 最大能力值的人员的能力值，都加：a/b 如果超过最大值，就设置为最大能力值。
# 例如：deviceID=35制程，有3个人可以做。3个人的能力值分别为：20,36,40。
# 则调整后的能力值分别为：20+35/3:31.7, 36+35/3:40（超过最大能力值40，就为40）, 40（最大值不调整）
def GetManAbility(AllDevicetypeID2ManIDArray, AllPlanlogResult, All_ProcedureID2DevicetypeID_dict, nAllManNumber):
    global g_DeviceTypeID2ab_disc

    if len(AllDevicetypeID2ManIDArray)<=0:
        return
    # 开始统计总的人数和实际总的制程数
    # 统计总的人数
    # 按照人员ID排序
    AllDevicetypeID2ManIDArray = sorted(AllDevicetypeID2ManIDArray, key=lambda x: (x[1], x[0], x[2]))
    # 计算能力值
    CurrentManID = AllDevicetypeID2ManIDArray[0][1] # 初始化用第一条人员的ID
    ManAblity = 100   # 人员的能力值
    # 定义字典：DeviceID共有几个人可以做？
    # 2、然后统计该制程，有几个可以做？假设为：b。也就是说，这个制程要这几个人来分配。
    DeviceTypeID2nCanDoManNumbers_disc = {}
    for i in range(len(AllDevicetypeID2ManIDArray)):
        # 赋值 DeviceID共有几个人可以做 字典
        if DeviceTypeID2nCanDoManNumbers_disc.has_key(AllDevicetypeID2ManIDArray[i][0]) == False:
            DeviceTypeID2nCanDoManNumbers_disc[AllDevicetypeID2ManIDArray[i][0]] = 1
        else:
            DeviceTypeID2nCanDoManNumbers_disc[AllDevicetypeID2ManIDArray[i][0]] += 1

    nCurrentManFirstLine = 0 # 需要记录当前人员的第一个位置，为了后面从此开始，计算能力值
    for i in range(len(AllDevicetypeID2ManIDArray)):
        # 依次减去该人的每个制程，
        if AllDevicetypeID2ManIDArray[i][1] <> CurrentManID:  # 到了下一个人
            # [100 - A1(总的人数 - 会的人数) - ... An(总的人数 - 会的人数)]/该技能会的人数
            # 同一个人的能力值公式里，分子都是相同的，只有分母不同
            # 依次填写当前该人CurrentManID的所有会的技能的能力值
            for k in range(nCurrentManFirstLine, i):
                AllDevicetypeID2ManIDArray[k][2] = ManAblity / DeviceTypeID2nCanDoManNumbers_disc[AllDevicetypeID2ManIDArray[k][0]]
            # 当前的人员ID
            CurrentManID = AllDevicetypeID2ManIDArray[i][1]
            ManAblity = 100  # 人员的能力值初始化
            nCurrentManFirstLine = i  # 需要记录当前人员的第一个位置，为了后面从此开始，计算能力值

        # 计算分子：
        # 100 - An(总的人数 - 会的人数)
        ManAblity -= (nAllManNumber - DeviceTypeID2nCanDoManNumbers_disc[AllDevicetypeID2ManIDArray[i][0]])
    # 最后一个人，计算公式里的分母：即【该技能会的人数】。
    # 同一个人的能力值公式里，分子都是相同的，只有分母不同
    # 依次填写当前该人CurrentManID的所有会的技能的能力值
    for k in range(nCurrentManFirstLine, i+1):  # range(x,y)，其中y值是<y，而不是<=y
        AllDevicetypeID2ManIDArray[k][2] = ManAblity / DeviceTypeID2nCanDoManNumbers_disc[AllDevicetypeID2ManIDArray[k][0]]

    # 2、《《《AllPlanlogResult》》》表，是planlog和workorder表合成出来的列表
    # 【0】PL.`id`, 【1】PL.`workorder_id`, 【2】WO.`name`, 【3】WO.`number`, 【4】PL.`finishnum`, 【5】PL.`maxnum`，【6】PL.`yjkg`
    # 【7】PL.`procedure1_man_id` ~ 【18】PL.`procedure12_man_id`
    # 【19】PL.`procedure1_startdate` ~ 【30】PL.`procedure12_startdate`
    # 【31】PL.`procedure1_finishdate` ~ 【42】PL.`procedure12_finishdate`
    # 【55】PL.`procedure1_id` ~ 【66】PL.`procedure12_id`
    # 新添加：每个制程有多少需要排程？
    # 定义字典：每个DeviceID共有多少个需要做？
    # 1、为了均衡排程，统计每个制程即devicetypeID(procedureIDn)在所有要排程的工单里有多少？假设为：a
    DeviceTypeID2nSum_disc = {}
    for PlanlogRow in AllPlanlogResult:
        i = PlanlogRow[4] + 1  # 只判断当前工单完成制程的下一个制程即可
        # 当前第一个要做的制程开始时间不是“0000-00-00 00:00:00”代表该制程已经开始做了。就要记录该制程的人员信息
        # PlanlogRow[19 + i - 1]是procedureN_startdate，PlanlogRow[31 + i - 1]是procedureN_finishdate
        while(i <= PlanlogRow[5] and PlanlogRow[55 + i - 1] != 0):  # 找到一个procedureID，即DeviceTypeID
            if(DeviceTypeID2nSum_disc.has_key(All_ProcedureID2DevicetypeID_dict[PlanlogRow[55 + i - 1]]) == False):
                DeviceTypeID2nSum_disc[All_ProcedureID2DevicetypeID_dict[PlanlogRow[55 + i - 1]]] = 1       # 新的
            else:
                DeviceTypeID2nSum_disc[All_ProcedureID2DevicetypeID_dict[PlanlogRow[55 + i - 1]]] += 1      # 已经有了，加1
            i = i+1

    # 3、最后 不是 最大能力值的人员的能力值，都加：a/b 如果超过最大值，就设置为最大能力值。
    # 先计算a/b
    # 通过遍历keys()来获取所有的键
    for k2 in DeviceTypeID2nCanDoManNumbers_disc.keys():  # b，这个一定是完整的
        bExist = False
        for k1 in DeviceTypeID2nSum_disc.keys(): # a，这个字典可能是不完整的
            if(k1 == k2):
                # *******目前处理阀值先定义为1，越小能力值处理后，越趋同*************
                g_DeviceTypeID2ab_disc[k1] = DeviceTypeID2nSum_disc[k1] / (DeviceTypeID2nCanDoManNumbers_disc[k2] * 1)
                bExist = True
                break
        if not bExist:
            g_DeviceTypeID2ab_disc[k2] = 0    # 没有的，就默认为0

    AllDevicetypeID2ManIDArray = sorted(AllDevicetypeID2ManIDArray, key=lambda x: (x[0], x[2], x[1]), reverse=True)   # 按同一个deviceType，能力值降序排序
    i = 0
    while i < len(AllDevicetypeID2ManIDArray):
        # 每一组相同的devieTypeID中，排在第一位的AllDevicetypeID2ManIDArray[i][2]就是最大的ability。因为是降序排列的
        if( i+1 < len(AllDevicetypeID2ManIDArray) ):
            for j in range(i+1, len(AllDevicetypeID2ManIDArray)):   # 从下一个开始，理论上下面都是相同的deviceTypeID
                if( AllDevicetypeID2ManIDArray[i][0] == AllDevicetypeID2ManIDArray[j][0] ):   # deviceTypeID相同，就加上a/b
                    if( AllDevicetypeID2ManIDArray[j][2] + g_DeviceTypeID2ab_disc[AllDevicetypeID2ManIDArray[i][0]] < AllDevicetypeID2ManIDArray[i][2] ):
                        AllDevicetypeID2ManIDArray[j][2] += g_DeviceTypeID2ab_disc[AllDevicetypeID2ManIDArray[i][0]]  # 小于就加a/b
                    else:
                        AllDevicetypeID2ManIDArray[j][2] = AllDevicetypeID2ManIDArray[i][2] # 大于就直接赋值
                else:
                    i = j   # 到了下一组
                    bHasUpdate = True
                    break
            if(j == len(AllDevicetypeID2ManIDArray)-1): # 到了最后
                break

    # 最后返回带有能力值的数组
    AllDevicetypeID2ManIDArray = sorted(AllDevicetypeID2ManIDArray, key=lambda x: (x[0], x[1], x[2]))   # 恢复排序
    return (AllDevicetypeID2ManIDArray)

# 取得所有人员的工作时间表，制程组成所有的人员：制程ID / 人员，同时也可以反查：人员 / 制程ID
def GetAllManInfoTable(startTime, AllVacationContents, AllPlanlogResult, All_ProcedureID2DevicetypeID_dict):
    try:
        conn = pymysql.Connect(
            host=g_DatabaseIP,
            port=dbport,
            user=dbuser,
            passwd=dbpasswd,
            db=database,
            charset='utf8',
            local_infile=1
        )
        # 使用cursor()方法获取操作游标
        cursor = conn.cursor()
        cursor.execute('SET SESSION WAIT_TIMEOUT = 86400')

        # 先取得所有人员，以及能做的制程列表
        sql = "select `id`,`name`," \
              "`devicetype1_id`,`devicetype2_id`,`devicetype3_id`,`devicetype4_id`," \
              "`devicetype5_id`,`devicetype6_id`,`devicetype7_id`,`devicetype8_id`," \
              "`devicetype9_id`,`devicetype10_id`,`devicetype11_id`,`devicetype12_id`, " \
              "`devicetype13_id`,`devicetype14_id`,`devicetype15_id`,`devicetype16_id`, " \
              "`devicetype17_id`,`devicetype18_id`,`devicetype19_id`,`devicetype20_id`, " \
              "`devicetype21_id`,`devicetype22_id`,`devicetype23_id`,`devicetype24_id`, " \
              "`devicetype25_id`,`devicetype26_id`,`devicetype27_id`,`devicetype28_id`, " \
              "`devicetype29_id`,`devicetype30_id` " \
              " from fa_aps_man where state = '1' and `name` not in ('陳俊圻','莊韻慈')"
        result = cursor.execute(sql)

        if result:
            AllMan2AllDevicetypeIDArray = cursor.fetchall()

        if len(AllMan2AllDevicetypeIDArray) == 0:
            print('error: no man, no man can be arranged!!!')
        else:
            # 取得所有的可以工作的人员总数，为了后面的统计工时fa_aps_ygyg表
            SUMWorkerNums = len(AllMan2AllDevicetypeIDArray)

        # 1、先取得所有制程对应人员的对应表
        OneDevicetypeID2ManIDArray = DevicetypeID2ManIDClass()
        AllDevicetypeID2ManIDArray = []
        for row in AllMan2AllDevicetypeIDArray:
            for i in range(2, len(row)):  # 对应该人的所有的工作
                if row[i] <> 0:
                    # 在制程与人的对应表查找如果2项都不同，就添加
                    bExist = False  # 是不是存在？
                    for PID in AllDevicetypeID2ManIDArray:
                        if row[i] == PID[0] and row[0] == PID[1]:
                            bExist = True
                            break
                    # 不存在，追加
                    if not bExist:
                        OneDevicetypeID2ManIDArray.DevicetypeID = row[i]
                        OneDevicetypeID2ManIDArray.manID = row[0]
                        AllDevicetypeID2ManIDArray.append(OneDevicetypeID2ManIDArray.to_list())
        # 变成NP表，以便去重
        npArr = np.array(AllDevicetypeID2ManIDArray)
        # 去掉重复的行
        mylist = np.array(list(set([tuple(t) for t in npArr])))
        # 转成列表
        AllDevicetypeID2ManIDArray = mylist.tolist()
        # 将工序与人员ID排序
        AllDevicetypeID2ManIDArray = sorted(AllDevicetypeID2ManIDArray)
        # 一定要先去掉重复的行后，再取得人员的能力值
        AllDevicetypeID2ManIDArray = GetManAbility(AllDevicetypeID2ManIDArray, AllPlanlogResult, All_ProcedureID2DevicetypeID_dict, SUMWorkerNums)

        # 2、再取得所有人员对应的工作时间表
        # 先保存所有的人员ID
        OneManWorkingArray = ManWorkingTimeClass()
        AllManWorkingArray = []
        # 所有人员从当前时间开始，默认都是空闲的
        for row in AllMan2AllDevicetypeIDArray:
            OneManWorkingArray.manID = row[0]  # manid
            OneManWorkingArray.beginWorkTime = startTime  # startdate
            OneManWorkingArray.endWorkTime = startTime  # startTime
            AllManWorkingArray.append(OneManWorkingArray.to_list())

        # 循环插入ID与人
        for OutRow in AllVacationContents:  # 休假的表
            beginWorkTime = AdjustToWorkingHours(OutRow[1], 0, 0, ())
            endWorkTime = AdjustToWorkingHours(OutRow[2], 0, 0, ())
            if OutRow[0] == 0:  # 全员休假
                for row in AllMan2AllDevicetypeIDArray:
                    OneManWorkingArray.manID = row[0]  # manid
                    OneManWorkingArray.beginWorkTime = beginWorkTime  # startdate
                    OneManWorkingArray.endWorkTime = endWorkTime  # enddate
                    AllManWorkingArray.append(OneManWorkingArray.to_list())
            else:
                OneManWorkingArray.manID = OutRow[0]  # manid
                OneManWorkingArray.beginWorkTime = beginWorkTime  # startdate
                OneManWorkingArray.endWorkTime = endWorkTime  # enddate
                AllManWorkingArray.append(OneManWorkingArray.to_list())

        # 全员休假表g_allVk_v
        for row in g_allVk_v:
            vkTime = datetime.datetime.strptime(row[0] + g_MorningStartWorktime, '%Y-%m-%d%H:%M')
            if startTime > vkTime:
                continue
            else:
                beginWorkTime = datetime.datetime.strptime(row[0] + g_MorningStartWorktime, '%Y-%m-%d%H:%M')
                beginWorkTime = AdjustToWorkingHours(beginWorkTime, 0, 0, ())
                endWorkTime = datetime.datetime.strptime(row[0] + g_AfternoonEndWorktime, '%Y-%m-%d%H:%M')
                endWorkTime = AdjustToWorkingHours(endWorkTime, 0, 0, ())
                for row in AllMan2AllDevicetypeIDArray:
                    OneManWorkingArray.manID = row[0]  # manid
                    OneManWorkingArray.beginWorkTime = beginWorkTime  # startdate
                    OneManWorkingArray.endWorkTime = endWorkTime  # enddate
                    AllManWorkingArray.append(OneManWorkingArray.to_list())

        # 取正在进行的制程中哪些人员被占用
        for PlanlogRow in AllPlanlogResult:
            # 取每个manID对比，用后面的datetime更新
            i = PlanlogRow[4]+1 # 只判断当前工单完成制程的下一个制程即可
            # 当前第一个要做的制程开始时间不是“0000-00-00 00:00:00”代表该制程已经开始做了。就要记录该制程的人员信息
            # PlanlogRow[19 + i - 1]是procedureN_startdate，PlanlogRow[31 + i - 1]是procedureN_finishdate
            if i <= PlanlogRow[5] and PlanlogRow[19 + i - 1] != None and PlanlogRow[31 + i - 1] != None and \
                    PlanlogRow[19 + i - 1] != '0000-00-00 00:00:00' and PlanlogRow[31 + i - 1] != '0000-00-00 00:00:00':
                if startTime >= PlanlogRow[19 + i - 1] and startTime <= PlanlogRow[31 + i - 1]:
                    OneManWorkingArray.manID =  PlanlogRow[7 + i - 1]  # manid
                    # if OneManWorkingArray.manID == 0:
                    #     pass
                    OneManWorkingArray.beginWorkTime = PlanlogRow[19 + i - 1]  # finishdate
                    OneManWorkingArray.endWorkTime = PlanlogRow[31 + i - 1]  # enddate
                    AllManWorkingArray.append(OneManWorkingArray.to_list())

        # 变成NP表，以便去重
        npArr = np.array(AllManWorkingArray)
        # 去掉重复的行
        mylist = np.array(list(set([tuple(t) for t in npArr])))
        # 转成列表
        AllManWorkingArray = mylist.tolist()
        # 列表排序，按开始时间排序
        AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[1], x[2]))
        # 最后对AllManWorkingArray列表整理，合并同一个人的重叠时间段，保证同一个人的各个不同的工作时间段（休假也看成被占用，相当于工作时段）没有交叉
        for i in range(len(AllManWorkingArray)):
            j = i + 1
            while j < len(AllManWorkingArray):
                if AllManWorkingArray[i][0] == AllManWorkingArray[j][0]:  # manID同
                    # 第1种情况，包含：如果第i行包含在第j行时间范围内，第i行多余，要删除
                    if AllManWorkingArray[i][1] >= AllManWorkingArray[j][1] and AllManWorkingArray[i][2] <= \
                            AllManWorkingArray[j][2]:
                        del AllManWorkingArray[i]
                        continue    # 再从当前项判断
                    # 第2种情况，反包：如果第j行包含在第i行时间范围内，第j行多余，要删除
                    elif AllManWorkingArray[j][1] >= AllManWorkingArray[i][1] and AllManWorkingArray[j][2] <= \
                            AllManWorkingArray[i][2]:
                        del AllManWorkingArray[j]
                        continue    # 再从当前项判断
                    # 第3种情况，交错有交集，取并集，合并后，要删除小的集合
                    elif AllManWorkingArray[i][1] >= AllManWorkingArray[j][1] and AllManWorkingArray[j][2] >= AllManWorkingArray[i][1] \
                            and AllManWorkingArray[j][2] <= AllManWorkingArray[i][2]:
                        AllManWorkingArray[i][1] = AllManWorkingArray[j][1]
                        del AllManWorkingArray[j]
                        continue    # 再从当前项判断
                    # 第4种情况，交错有交集，取并集，合并后，要删除小的集合
                    elif AllManWorkingArray[i][1] < AllManWorkingArray[j][1] and AllManWorkingArray[i][2] >= \
                            AllManWorkingArray[j][1] and AllManWorkingArray[i][2] <= AllManWorkingArray[j][2]:
                        AllManWorkingArray[i][2] = AllManWorkingArray[j][2]
                        del AllManWorkingArray[j]
                        continue    # 再从当前项判断
                j += 1

        # 列表排序，结束的时间更重要，要排在开始时间的前面，并取得当前与下个工作空闲的时间段
        AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[2], x[1]))
        AllManWorkingArray = GetSortedAllManWorkingArrayAndToNextWorkFreetime(AllManWorkingArray)

        # 将其他的剩余人员也加入，只是工作时长为-1，代表后面时间完全空闲
        # 这个部分只可能出现一次，当开始派单时，全部的人员已经都有覆盖到时，这些内容就要被更新了
        OneManWorkingArray.clear()
        for row1 in AllMan2AllDevicetypeIDArray:
            bExist = False
            for row2 in AllManWorkingArray:
                if row1[0] == row2[0]:  # 已经有该人员存在
                    bExist = True
                    break
            if not bExist:
                OneManWorkingArray.manID = row1[0]    # manid
                OneManWorkingArray.endWorkTime = startTime  # 开始时间段已经是默认的2019-01-01，然后到目前的时刻作为结束的时间点
                OneManWorkingArray.ToNextWorkFreetime = -1
                AllManWorkingArray.append(OneManWorkingArray.to_list())

        # 列表排序，结束的时间更重要，要排在开始时间的前面，最晚结束的时间排在前面，如果中间没有空闲的时间，就按最晚空闲的时间算
        AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[2], x[1]), reverse=True)
        # 返回
        return (AllManWorkingArray, AllMan2AllDevicetypeIDArray, AllDevicetypeID2ManIDArray, SUMWorkerNums)
    except:
        conn.rollback()
        #conn.close()
        print "database connect error. GetAllProcedureID2Man function is wrong"

######################################
# 挑出由谁干，从什么时间开始干
# 考虑最早结束，就安排
# 当要安排的时间相同，按能力值大安排
# 返回值：(manID, CurrentProcedureX_Startdatetime, AllManWorkingArray_O)
def WhoFromWhenDo_byTime(DevicetypeID, startTime, manHours, AllManWorkingArray_O, AllDevicetypeID2ManIDArray, ExclusiveManList):
    # AllManWorkingArray_O人员工作记录表按结束时间升序排列，越早结束越可能被先安排
    AllManWorkingArray_O = sorted(AllManWorkingArray_O, key=lambda x: (x[0], x[2], x[1]))
    # 先计算该制程的预计结束时间
    returnStartDatetime = startTime

    # 预先判断该devicetypeID是不是有多人可以做？如果是，才可以考虑排他列表ExclusiveManList
    nCanDoDevicetypeIDNumbers = 0
    if len(ExclusiveManList) > 0:
        for DevicetypeID2ManIDRow in AllDevicetypeID2ManIDArray:
            if DevicetypeID == DevicetypeID2ManIDRow[0]:
                nCanDoDevicetypeIDNumbers += 1
                if nCanDoDevicetypeIDNumbers > len(ExclusiveManList):   # 有超过排他的人可以做，就可以退出，继续下面的
                    break
        if nCanDoDevicetypeIDNumbers <= len(ExclusiveManList):  # 排他的人已经满员，不能再考虑排他，只能清空
            ExclusiveManList = []

    # 先考虑中间空闲的时间段
    manID = 0  # 初始化一个人员ID为0
    preFreeTime = AllManWorkingArray_O[0][2]    # 上一个被安排的人的最后空闲时间
    # AllDevicetypeID2ManIDArray: [self.DevicetypeID, self.manID, self.ability]
    nCurrentAbility = 0 # 当要安排的时间相同，按能力值大安排
    for DevicetypeID2ManIDRow in AllDevicetypeID2ManIDArray:
        # 加快效率，AllDevicetypeID2ManIDArray已经按devicetypeID排序了，如果大于DevicetypeID，后面就不可能再有该ID啦
        if DevicetypeID2ManIDRow[0] > DevicetypeID:
            break
        # 在当前devicetypeID对应manID的表中，查找可以做DevicetypeID的人，可能有多人
        if DevicetypeID == DevicetypeID2ManIDRow[0]:
            # 找到一个能做该制程的人，再判断是否满足第1条
            # 在AllManWorkingArray_O中，就是按照manID排序的。而AllDevicetypeID2ManIDArray也是按照manID排序的。
            # AllManWorkingArray_O: self.manID, self.beginWorkTime, self.endWorkTime, self.ToNextWorkFreetime
            for i in range(0, len(AllManWorkingArray_O)):  # 第5层：找人 (for i in range(lenAllManWorkingArray_O))
                # 找到在该时间点空闲的人，并且该人与下段工作开始的时间段要大于等于该制程所要花费的时间
                if DevicetypeID2ManIDRow[1] == AllManWorkingArray_O[i][0]:
                    # 预计结束时间，是否在下一个工作时间之前？

                    # 判断是不是在排他列表中
                    if len(ExclusiveManList)>0:
                        if AllManWorkingArray_O[i][0] in ExclusiveManList:
                            continue

                    # 这个是判断：中间空闲的时间段要能插入
                    if AllManWorkingArray_O[i][3] != -1:
                        if AllManWorkingArray_O[i][3] >= manHours:  # 碎片时间可以安排该制程
                            if returnStartDatetime >= AllManWorkingArray_O[i][2]:
                                # 要开始的时间 + 该制程所需的时间段，就是该制程将要结束的时间点
                                tempEndDateTime = AdjustToWorkingHours(returnStartDatetime, manHours, 0, ())
                                # 因为AllManWorkingArray_O[i][3] != -1，所以AllManWorkingArray_O[i][0]后面有人，且一定是同一个人，否则就是-1啦
                                if tempEndDateTime <= AllManWorkingArray_O[i+1][1]: # 已经满足了第1条
                                    if manID == 0:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = startTime
                                        break

                                    # 先暂时保存能做该事的人的最后空闲的时间，看谁的时间结束的早，就选谁
                                    # 只有小于当前要安排的时间returnStartDatetime，才考虑要不要更换
                                    if returnStartDatetime > AllManWorkingArray_O[i][2]:
                                        if AllManWorkingArray_O[i][2] >= startTime:  # startTime是初始安排的时间
                                            tempEndDateTime = AdjustToWorkingHours(AllManWorkingArray_O[i][2], manHours, 0, ())
                                            if tempEndDateTime <= AllManWorkingArray_O[i + 1][1]:  # 碎块时间可以安排
                                                returnStartDatetime = AllManWorkingArray_O[i][2]
                                                manID = AllManWorkingArray_O[i][0]
                                                nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        else:
                                            returnStartDatetime = startTime
                                            manID = AllManWorkingArray_O[i][0]
                                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                                    elif returnStartDatetime == AllManWorkingArray_O[i][2]:
                                        if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                                            manID = AllManWorkingArray_O[i][0]
                                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                            else:
                                tempEndDateTime = AdjustToWorkingHours(AllManWorkingArray_O[i][2], manHours, 0, ())
                                if tempEndDateTime <= AllManWorkingArray_O[i+1][1]: # 满足碎块时间大于工序时间
                                    if manID == 0:
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = AllManWorkingArray_O[i][2]
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        break

                                    # 先暂时保存能做该事的人的最后空闲的时间，看谁的时间结束的早，就选谁
                                    # 只有小于当前要安排的时间returnStartDatetime，才考虑要不要更换
                                    if returnStartDatetime > AllManWorkingArray_O[i][2]:
                                        if AllManWorkingArray_O[i][2] >= startTime:  # startTime是初始安排的时间
                                            tempEndDateTime = AdjustToWorkingHours(AllManWorkingArray_O[i][2], manHours, 0, ())
                                            if tempEndDateTime <= AllManWorkingArray_O[i + 1][1]:  # 碎块时间可以安排
                                                returnStartDatetime = AllManWorkingArray_O[i][2]
                                                manID = AllManWorkingArray_O[i][0]
                                                nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        else:
                                            returnStartDatetime = startTime
                                            manID = AllManWorkingArray_O[i][0]
                                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                                    elif returnStartDatetime == AllManWorkingArray_O[i][2]:
                                        if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                                            manID = AllManWorkingArray_O[i][0]
                                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                    else: #AllManWorkingArray_O[i][3] == -1
                        # 最初先安排一个人做备选，以防止manid == 0，
                        # 因为AllManWorkingArray_O已经按结束时间升序排列，即最早结束的排前面，也就是该被安排的人就是最早结束的人
                        if manID == 0:
                            manID = AllManWorkingArray_O[i][0]
                            if startTime >= AllManWorkingArray_O[i][2]:
                                returnStartDatetime = startTime
                            else:
                                returnStartDatetime = AllManWorkingArray_O[i][2]
                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                            preFreeTime = AllManWorkingArray_O[i][2]
                            break

                        # 先暂时保存能做该事的人的最后空闲的时间，看谁的时间结束的早，就选谁
                        # 只有小于当前要安排的时间returnStartDatetime，才考虑要不要更换
                        if returnStartDatetime > AllManWorkingArray_O[i][2]:
                            manID = AllManWorkingArray_O[i][0]
                            if AllManWorkingArray_O[i][2] >= startTime: # startTime是初始安排的时间
                                returnStartDatetime = AllManWorkingArray_O[i][2]
                            else:
                                returnStartDatetime = startTime
                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                        elif returnStartDatetime == AllManWorkingArray_O[i][2]:
                            if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                                manID = AllManWorkingArray_O[i][0]
                                nCurrentAbility = DevicetypeID2ManIDRow[2]
    # 已经找到了，返回
    if manID <> 0:
        # 人员工作记录表恢复顺序，按结束时间降序排列
        AllManWorkingArray_O = sorted(AllManWorkingArray_O, key=lambda x: (x[0], x[2], x[1]), reverse=True)
        return (manID, returnStartDatetime, AllManWorkingArray_O, ExclusiveManList)
    else:
        print "ERROR！！！ manID ==0, DevicetypeID = " , DevicetypeID

    return (manID, startTime, AllManWorkingArray_O, ExclusiveManList)

######################################
# 挑出由谁干，从什么时间开始干
# 第1条、按照人员对技能的能力数值越大越优先安排。
# 第2条、如果能力数值虽然小，但空闲的时间与希望安排的时间越接近，也可能被安排
# 第3条、如果最后的结束时间是-1，代表后面都是空闲时间
# 如果能做这个事的人比较忙，就选其他能做该事的人(要从AllDevicetypeID2ManIDArray表里)，要满足以上条件
# 返回值：(manID, CurrentProcedureX_Startdatetime, AllManWorkingArray_O)
def WhoFromWhenDo_byAbility(DevicetypeID, startTime, manHours, AllManWorkingArray_O, AllDevicetypeID2ManIDArray, ExclusiveManList):
    # AllManWorkingArray_O人员工作记录表按结束时间升序排列，越早结束越可能被先安排
    AllManWorkingArray_O = sorted(AllManWorkingArray_O, key=lambda x: (x[0], x[2], x[1]))
    # 先计算该制程的预计结束时间
    returnStartDatetime = startTime

    # 预先判断该devicetypeID是不是有多人可以做？如果是，才可以考虑排他列表ExclusiveManList
    nCanDoDevicetypeIDNumbers = 0
    if len(ExclusiveManList) > 0:
        for DevicetypeID2ManIDRow in AllDevicetypeID2ManIDArray:
            if DevicetypeID == DevicetypeID2ManIDRow[0]:
                nCanDoDevicetypeIDNumbers += 1
                if nCanDoDevicetypeIDNumbers > len(ExclusiveManList):   # 有超过排他的人可以做，就可以退出，继续下面的
                    break
        if nCanDoDevicetypeIDNumbers <= len(ExclusiveManList):  # 排他的人已经满员，不能再考虑排他，只能清空
            ExclusiveManList = []

    # 先考虑中间空闲的时间段
    nCurrentAbility = 0 # 当前的能力值，初始化为0
    manID = 0  # 初始化一个人员ID为0
    preFreeTime = AllManWorkingArray_O[0][2]    # 上一个被安排的人的最后空闲时间
    for DevicetypeID2ManIDRow in AllDevicetypeID2ManIDArray:
        # 加快效率，AllDevicetypeID2ManIDArray已经按devicetypeID排序了，如果大于DevicetypeID，后面就不可能再有该ID啦
        if DevicetypeID2ManIDRow[0] > DevicetypeID:
            break
        # 在当前devicetypeID对应manID的表中，查找可以做DevicetypeID的人，可能有多人
        if DevicetypeID == DevicetypeID2ManIDRow[0]:
            # 找到一个能做该制程的人，再判断是否满足第1条
            # 在AllManWorkingArray_O中，就是按照manID排序的。而AllDevicetypeID2ManIDArray也是按照manID排序的。
            for i in range(0, len(AllManWorkingArray_O)):  # 第5层：找人 (for i in range(lenAllManWorkingArray_O))
                # 找到在该时间点空闲的人，并且该人与下段工作开始的时间段要大于等于该制程所要花费的时间
                if DevicetypeID2ManIDRow[1] == AllManWorkingArray_O[i][0]:
                    # 预计结束时间，是否在下一个工作时间之前？

                    # 判断是不是在排他列表中
                    if len(ExclusiveManList)>0:
                        if AllManWorkingArray_O[i][0] in ExclusiveManList:
                            continue

                    # 这个是判断：中间空闲的时间段要能插入
                    if AllManWorkingArray_O[i][3] != -1:
                        if AllManWorkingArray_O[i][3] >= manHours:  # 碎片时间可以安排该制程
                            if startTime >= AllManWorkingArray_O[i][2]:
                                # 要开始的时间 + 该制程所需的时间段，就是该制程将要结束的时间点
                                tempEndDateTime = AdjustToWorkingHours(startTime, manHours, 0, ())
                                # 因为AllManWorkingArray_O[i][3] != -1，所以AllManWorkingArray_O[i][0]后面有人，且一定是同一个人，否则就是-1啦
                                if tempEndDateTime <= AllManWorkingArray_O[i+1][1]: # 已经满足了第1条
                                    # 最初先安排一个人做备选，以防止manid == 0，
                                    # 因为AllManWorkingArray_O已经按结束时间升序排列，即最早结束的排前面，也就是该被安排的人就是最早结束的人
                                    if manID == 0:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = startTime
                                        preFreeTime = AllManWorkingArray_O[i][2]
                                        break

                                    # 能力值虽然大，但能力值低的人的空闲时间N小时，N小时看做N个能力值
                                    # 取得能力值，挑能力数值大的，越高越优先安排
                                    if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = startTime
                                    # 如果能力值相同，就看谁结束的时间早，如果早，就安排谁做
                                    elif nCurrentAbility == DevicetypeID2ManIDRow[2]: # 如果能力值相同，就看谁结束的时间早，如果早，就安排谁做
                                        if preFreeTime > AllManWorkingArray_O[i][2]:    # 前一个被安排的人比当前的人忙
                                            if startTime > AllManWorkingArray_O[i][2]:
                                                nCurrentAbility = DevicetypeID2ManIDRow[2]
                                                manID = AllManWorkingArray_O[i][0]
                                                returnStartDatetime = startTime
                            else:
                                tempEndDateTime = AdjustToWorkingHours(AllManWorkingArray_O[i][2], manHours, 0, ())
                                if tempEndDateTime <= AllManWorkingArray_O[i+1][1]: # 已经满足了第1条
                                    # 最初先安排一个人做备选，以防止manid == 0，
                                    # 因为AllManWorkingArray_O已经按结束时间升序排列，即最早结束的排前面，也就是该被安排的人就是最早结束的人
                                    if manID == 0:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = AllManWorkingArray_O[i][2]
                                        preFreeTime = AllManWorkingArray_O[i][2]
                                        break

                                    # 取得能力值，挑能力数值大的，越高越优先安排
                                    if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                                        if AllManWorkingArray_O[i][2] < returnStartDatetime:
                                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                                            manID = AllManWorkingArray_O[i][0]
                                            returnStartDatetime = AllManWorkingArray_O[i][2]
                                    # 如果能力值相同，就看谁结束的时间早，如果早，就安排谁做
                                    elif nCurrentAbility == DevicetypeID2ManIDRow[2]: # 如果能力值相同，就看谁结束的时间早，如果早，就安排谁做
                                        if preFreeTime > AllManWorkingArray_O[i][2]:    # 前一个被安排的人比当前的人忙
                                            if returnStartDatetime > AllManWorkingArray_O[i][2]:
                                                nCurrentAbility = DevicetypeID2ManIDRow[2]
                                                manID = AllManWorkingArray_O[i][0]
                                                returnStartDatetime = startTime
                                                preFreeTime = AllManWorkingArray_O[i][2]
                                    # else:  # 虽然这个人的能力值低，但他太空了，也要安排他
                                    #     nCurrentAbility = DevicetypeID2ManIDRow[2]
                                    #     manID = AllManWorkingArray_O[i][0]
                                    #     if AllManWorkingArray_O[i][2] <= startTime:
                                    #         returnStartDatetime = startTime
                                    #     else:
                                    #         returnStartDatetime = AllManWorkingArray_O[i][2]
                    else: #AllManWorkingArray_O[i][3] == -1
                        # 最初先安排一个人做备选，以防止manid == 0，
                        # 因为AllManWorkingArray_O已经按结束时间升序排列，即最早结束的排前面，也就是该被安排的人就是最早结束的人
                        if manID == 0:
                            nCurrentAbility = DevicetypeID2ManIDRow[2]
                            manID = AllManWorkingArray_O[i][0]
                            if startTime >= AllManWorkingArray_O[i][2]:
                                returnStartDatetime = startTime
                            else:
                                returnStartDatetime = AllManWorkingArray_O[i][2]
                            preFreeTime = AllManWorkingArray_O[i][2]
                            break

                        # 先暂时保存能做该事的人的最后空闲的时间，时间都允许下再看谁能力值大，就选谁
                        # 取得能力值，挑能力数值大的
                        if nCurrentAbility < DevicetypeID2ManIDRow[2]:
                            if returnStartDatetime >= AllManWorkingArray_O[i][2]:
                                if AllManWorkingArray_O[i][2] >= startTime:
                                    nCurrentAbility = DevicetypeID2ManIDRow[2]
                                    manID = AllManWorkingArray_O[i][0]
                                    returnStartDatetime = AllManWorkingArray_O[i][2]
                                else:
                                    nCurrentAbility = DevicetypeID2ManIDRow[2]
                                    manID = AllManWorkingArray_O[i][0]
                                    returnStartDatetime = startTime
                            else:
                                nCurrentAbility = DevicetypeID2ManIDRow[2]
                                manID = AllManWorkingArray_O[i][0]
                                returnStartDatetime = AllManWorkingArray_O[i][2]
                        elif nCurrentAbility == DevicetypeID2ManIDRow[2]:   # 如果能力值相同，就看谁结束的时间早，如果早，就安排谁做
                            if preFreeTime > AllManWorkingArray_O[i][2]:    # 前一个被安排的人比当前的人忙
                                if returnStartDatetime >= AllManWorkingArray_O[i][2]:
                                    if AllManWorkingArray_O[i][2] >= startTime:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = AllManWorkingArray_O[i][2]
                                    else:
                                        nCurrentAbility = DevicetypeID2ManIDRow[2]
                                        manID = AllManWorkingArray_O[i][0]
                                        returnStartDatetime = startTime
                                    preFreeTime = AllManWorkingArray_O[i][2]
    # 已经找到了，返回
    if manID <> 0:
        # 人员工作记录表恢复顺序，按结束时间降序排列
        AllManWorkingArray_O = sorted(AllManWorkingArray_O, key=lambda x: (x[0], x[2], x[1]), reverse=True)
        return (manID, returnStartDatetime, AllManWorkingArray_O, ExclusiveManList)
    else:
        print "ERROR！！！ manID ==0, DevicetypeID = " , DevicetypeID

    return (manID, startTime, AllManWorkingArray_O, ExclusiveManList)

# 核心排序工单，先后处理急单、未完成工单、其他的新工单
# 以下处理，要得到每个工单内各个制程的开始时间，填写fa_aps_planlog表的procedure1_startdate~ procedure8_startdate，
# procedure1_finishdate~ procedure8_finishdate，procedure1_man_id~ procedure8_man_id
# 按最迟开始的时间作为最外面的循环
# 1、《《《《AlartSortedWorkorderList》》》列表元素
# 【0】planID = 0 【1】workorderID = 0 【2】beginWorkTime = None # 用该日期初始化，说明该人是空闲的
# 【3】ndWorkTime   = None   # 用该日期初始化，说明该人是空闲的
# 【4】maxnum = 0         # 该工单所有的工序数
# 【5】finishnum = 0      # 已经完成的工序数
# 【6】sumUnfinishedmanhours = 0     # 未完成的工序时间和
# 2、《《《AllPlanlogResult》》》表，是planlog和workorder表合成出来的列表
# 【0】PL.`id`, 【1】PL.`workorder_id`, 【2】WO.`name`, 【3】WO.`number`, 【4】PL.`finishnum`, 【5】PL.`maxnum`，【6】PL.`yjkg`
# 【7】PL.`procedure1_man_id` ~ 【18】PL.`procedure12_man_id`
# 【19】PL.`procedure1_startdate` ~ 【30】PL.`procedure12_startdate`
# 【31】PL.`procedure1_finishdate` ~ 【42】PL.`procedure12_finishdate`
# 【43】PL.`procedure1_manhours` ~ 【54】PL.`procedure12_manhours`
# 【55】PL.`procedure1_id` ~ 【66】PL.`procedure12_id`
# 【67】PL.`procedure1_preparedate` ~ 【78】PL.`procedure12_preparedate`
# 【79】PL.`procedure1_mannum` ~ 【90】PL.`procedure12_mannum`
# 3、《《《AllMan2AllDevicetypeIDArray》》》列表元素，人ID>>设备devicetypeID
# 【0】ManID,【1】name,【2】devicetype1_id,【3】devicetype2,【4】devicetype3_id,【5】devicetype4_id,【6】devicetype5_id,【7】devicetype6_id
# 4、《《《AllDevicetypeID2ManIDArray》》》列表元素，设备devicetypeID>>人ID
# 【0】procedure1_id,【1】ManID
# 5、《《《AllManWorkingArray_O》》》列表元素，最终都要填这个表，对所有人员的工作时间段记录，包含休假也认为是不能被安排的时间段
# 7、《《《AllUpdatePlanlogClassList》》》列表元素，用于更新数据库fa_aps_planlog/planlog0
# 【0】procedure1_man_id ~ 【11】procedure12_man_id
# 【12】procedure1_startdate ~ 【23】procedure12_startdate
# 【24】procedure1_finishdate ~ 【35】procedure12_finishdate
# 【36】procedure1_manhours ~ 【47】procedure12_manhours
# 【48】update_time，【49】jhwg， 【50】overtime_hours，【51】planlog_id，【52】workorder_id

# 唯一要在下面更新的数组
# 【0】manID 【1】beginWorkTime【2】endWorkTime 【3】距离下个工序的空闲的时间段，-1代表后面都空闲
def KernelArrangeWorkorder(startTime, WorkorderList, All_ProcedureID2DevicetypeID_dict, AllDevicetypeID2ManIDArray, AllPlanlogResult,
            AllManWorkingArray_O, AllUpdatePlanlogClassList_O, AllOvertimeContents, AllSubPlanlogClass, All_ProcedureID2Manhours_dict):
    # global g_countTest
    # 第一步：先处理急单 开始
    # 定义类信息，要更新planlog表的类
    OneUpdatePlanlogClassList = UpdatePlanlogClass()
    # 记录人员的更新信息到AllManWorkingArray_O列表中
    OneManWorkingArray = ManWorkingTimeClass()
    # 记录追加fa_aps_subplanlog表
    OneSubPlanlogClass = SubPlanlogClass()
    try:
        for WorkorderListRow in WorkorderList:  # 第1层（for WorkorderListRow in UnfinishedWorkorderList）
            # 清空源数据
            OneUpdatePlanlogClassList.clear()
            # if WorkorderListRow[0] in (531, 532):
            #     pass
            # 一个工单一条记录
            for planlogRow in AllPlanlogResult:  # 第2.1层：（for planlogRow in AllPlanlogResult）
                # planlog_id和workorder_id同
                if planlogRow[0] == WorkorderListRow[0] and planlogRow[1] == WorkorderListRow[1]:
                    # 初始化开始
                    # 对应每个要处理的制程的要开工的时间点
                    CurrentProcedureX_Startdatetime = startTime
                    CurrentProcedureX_Finishdatetime = startTime
                    nWhichProcedure = 0  # 在某个工单里的哪个制程

                    OneUpdatePlanlogClassList.planlog_id = WorkorderListRow[0]
                    OneUpdatePlanlogClassList.workorder_id = WorkorderListRow[1]
                    # 用原来的值先填充，已经完成的工序要保留原来的
                    for i in range(planlogRow[4]):
                        DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_man_id = planlogRow[{1}]".format(str(i+1),str(i+7))
                        exec (DynamicVariables)
                        DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_startdate = planlogRow[{1}]".format(str(i+1),str(i+19))
                        exec (DynamicVariables)
                        DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_finishdate = planlogRow[{1}]".format(str(i+1),str(i+31))
                        exec (DynamicVariables)
                    i = 0
                    # 用procedure里的时间更新planlog表的manhours
                    isContinue = True
                    for i in range(planlogRow[5]):
                        # 单个工序的时间，乘以num
                        #row[0] not in All_ProcedureID2Manhours_dict.keys()
                        DynamicVariables = "isContinue = (planlogRow[{0}] in All_ProcedureID2Manhours_dict.keys())".format(str(i+55))
                        exec (DynamicVariables)
                        if(isContinue == False):
                            DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_manhours = " \
                                               "1 * planlogRow[3]".format(str(i + 1), str(i + 55))
                        else:
                            DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_manhours = " \
                                               "All_ProcedureID2Manhours_dict[planlogRow[{1}]] * planlogRow[3]".format(str(i+1),str(i+55))
                        exec (DynamicVariables)

                    # 逻辑处理开始
                    while nWhichProcedure <= planlogRow[5]:
                        # 用于在某个工序如果要多人同时做，保存之前被安排的人，剩余的人才能被安排
                        ExclusiveManList = []
                        if nWhichProcedure == 0:    # 第一次
                            nWhichProcedure = planlogRow[4] + 1  # planlogRow[4]是完成的制程数，nWhichProcedure就是下一个即将要做的
                            # 当前第一个要做的制程开始时间为“0000-00-00 00:00:00”代表该制程没有做。否则就是已经开始做了，这个制程就不要排
                            # 当前时间在planlogRow[19 + nWhichProcedure - 1]开始和结束时间段planlogRow[31 + nWhichProcedure - 1]内：procedureN_startdate和procedureN_finishdate
                            if planlogRow[4] != 0:
                                if planlogRow[19 + nWhichProcedure - 1] != None and planlogRow[31 + nWhichProcedure - 1] != None and \
                                        planlogRow[19 + nWhichProcedure - 1] != '0000-00-00 00:00:00' and planlogRow[31 + nWhichProcedure - 1] != '0000-00-00 00:00:00':
                                    if startTime >= planlogRow[19 + nWhichProcedure - 1] and \
                                            startTime <= planlogRow[31 + nWhichProcedure - 1]:
                                        CurrentProcedureX_Startdatetime = planlogRow[31 + nWhichProcedure - 1]    # 从当前制程的结束时间作为开始时间

                            # 如果预计开工日比当前日期晚，就要用这个日期作为开始时间
                            tempDatetime = startTime
                            if planlogRow[6] is not None:   # 容错
                                tempDatetime = planlogRow[6]
                            if CurrentProcedureX_Startdatetime < tempDatetime:
                                CurrentProcedureX_Startdatetime = tempDatetime
                        # 该工序可以分多人同时做，计算每人多长时间
                        # 【0】PL.`id`, 【1】PL.`workorder_id`, 【2】WO.`name`, 【3】WO.`number`, 【4】PL.`finishnum`, 【5】PL.`maxnum`，【6】PL.`yjkg`
                        # 【7】PL.`procedure1_man_id` ~ 【18】PL.`procedure12_man_id`
                        # 【19】PL.`procedure1_startdate` ~ 【30】PL.`procedure12_startdate`
                        # 【31】PL.`procedure1_finishdate` ~ 【42】PL.`procedure12_finishdate`
                        # 【43】PL.`procedure1_manhours` ~ 【54】PL.`procedure12_manhours`
                        # 【55】PL.`procedure1_id` ~ 【66】PL.`procedure12_id`
                        # 【67】PL.`procedure1_preparedate` ~ 【78】PL.`procedure12_preparedate`
                        # 【79】PL.`procedure1_mannum` ~ 【90】PL.`procedure12_mannum`
                        # manhoursPerOneMan = planlogRow[43 + nWhichProcedure - 1] / planlogRow[79 + nWhichProcedure - 1]
                        manhoursPerOneMan = (All_ProcedureID2Manhours_dict[planlogRow[55 + nWhichProcedure -1]] * planlogRow[3]) / planlogRow[79 + nWhichProcedure - 1]
                        for i in range(1, planlogRow[79 + nWhichProcedure - 1]+1):
                            # 判断从该工单的哪个设备deviceID，按planlog的finishnum判断
                            # 找人：取开始制程的ID--AllViewResult[view_n][i]，对应该制程有谁空闲？如果没有空闲，最迟什么时间做？
                            CurrentProcedureX_Startdatetime = AdjustToWorkingHours(CurrentProcedureX_Startdatetime, 0, 0, ())
                            (manID, CurrentProcedureX_Startdatetime, AllManWorkingArray_O, ExclusiveManList) =\
                                WhoFromWhenDo_byTime( All_ProcedureID2DevicetypeID_dict[planlogRow[55 + nWhichProcedure - 1]],
                                               CurrentProcedureX_Startdatetime, manhoursPerOneMan,
                                               AllManWorkingArray_O, AllDevicetypeID2ManIDArray, ExclusiveManList)
                            # 因为CurrentProcedureX_Startdatetime有变更，再调整一次到正常的工作时间内
                            CurrentProcedureX_Startdatetime = AdjustToWorkingHours(CurrentProcedureX_Startdatetime, 0, 0, ())
                            if manID >= 0:  # 理论上不可能有manID = 0 的情况
                                # 只有工序有多人需要安排，才追加到排他列表中
                                if planlogRow[79 + nWhichProcedure - 1] > 1:
                                    ExclusiveManList.append(manID)
                                # 计算当前制程结束的时间
                                CurrentProcedureX_Finishdatetime = AdjustToWorkingHours(
                                    CurrentProcedureX_Startdatetime, manhoursPerOneMan, manID,
                                    AllOvertimeContents)

                                # 记录人员的更新信息到AllManWorkingArray_O列表中
                                if manID > 0:
                                    OneManWorkingArray.clear()
                                    OneManWorkingArray.manID = manID
                                    OneManWorkingArray.beginWorkTime = CurrentProcedureX_Startdatetime
                                    OneManWorkingArray.endWorkTime = CurrentProcedureX_Finishdatetime
                                    AllManWorkingArray_O.append(OneManWorkingArray.to_list())
                                    # 排序并统计到达下个休息时段的时间，如果是最后一个时间段，就是-1
                                    AllManWorkingArray_O = GetSortedAllManWorkingArrayAndToNextWorkFreetime(AllManWorkingArray_O)
                                    # 非常重要，要动态调整能力值
                                    AllDevicetypeID2ManIDArray = DynamicAbility(AllManWorkingArray_O, AllDevicetypeID2ManIDArray)

                                # 第一个是主负责人，需要添加到planlog表中，其他的人员，添加到fa_aps_subplanlog表中
                                if i != 1:
                                    # 追加到fa_aps_subplanlog表中？？？？
                                    OneSubPlanlogClass.clear()
                                    OneSubPlanlogClass.planlog_id = planlogRow[0]
                                    OneSubPlanlogClass.procedureX_id = planlogRow[55 + nWhichProcedure - 1]
                                    OneSubPlanlogClass.man_id = manID
                                    OneSubPlanlogClass.startdate = CurrentProcedureX_Startdatetime
                                    OneSubPlanlogClass.finishdate = CurrentProcedureX_Finishdatetime
                                    OneSubPlanlogClass.procedureX_manhours = manhoursPerOneMan
                                    # 追加到列表中
                                    AllSubPlanlogClass.append(OneSubPlanlogClass.to_list())
                                    # 同时进行不用调整开始时间
                                    # CurrentProcedureX_Startdatetime = CurrentProcedureX_Finishdatetime
                                    continue
                                else:
                                    # i == 1是主负责人
                                    # 第几个制程，按finishnum来判断？nWhichProcedure从1开始
                                    # procedureN_manID
                                    DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_man_id = manID".format(str(nWhichProcedure))
                                    exec (DynamicVariables)
                                    # procedureN_startdate
                                    DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_startdate = CurrentProcedureX_Startdatetime".format(str(nWhichProcedure))
                                    exec (DynamicVariables)
                                    # procedureN_finishdate
                                    DynamicVariables = "OneUpdatePlanlogClassList.procedure{0}_finishdate = CurrentProcedureX_Finishdatetime".format(str(nWhichProcedure))
                                    exec (DynamicVariables)

                                    # 计算加班工时
                                    if planlogRow[67 + nWhichProcedure - 1] != None and planlogRow[67 + nWhichProcedure - 1] != '0000-00-00 00:00:00' \
                                            and CurrentProcedureX_Finishdatetime > planlogRow[67 + nWhichProcedure - 1]:
                                        nMonths = (CurrentProcedureX_Finishdatetime - planlogRow[67 + nWhichProcedure - 1]).months
                                        nDays = (CurrentProcedureX_Finishdatetime - planlogRow[67 + nWhichProcedure - 1]).days
                                        nHours = (CurrentProcedureX_Finishdatetime - planlogRow[67 + nWhichProcedure - 1]).hours
                                        nMinites = (CurrentProcedureX_Finishdatetime - planlogRow[67 + nWhichProcedure - 1]).minutes
                                        # nSeconds = (CurrentProcedureX_Finishdatetime - planlogRow[67 + nWhichProcedure - 1]).seconds
                                        OneUpdatePlanlogClassList.overtime_hours += (nMonths * 22 * g_PerDayWorkingTime +
                                                                                     nDays * g_PerDayWorkingTime +
                                                                                     nHours + nMinites / float(60)) * \
                                                                                    planlogRow[79 + nWhichProcedure - 1]

                        # 循环变量自增加
                        nWhichProcedure += 1
                        # 如果开工时间在下班前半小时内，且该工序的完成时间在半小时内，就要从下一天开始
                        CurrentProcedureX_Startdatetime = CurrentProcedureX_Finishdatetime
                        LastCanArrange_Startdatetime = datetime.datetime.strptime(str(CurrentProcedureX_Startdatetime.date()) +
                                                                                  g_LastCanArrageWorktime, '%Y-%m-%d%H:%M')
                        if nWhichProcedure <= planlogRow[5] and \
                                CurrentProcedureX_Startdatetime >= LastCanArrange_Startdatetime and \
                                (All_ProcedureID2Manhours_dict[planlogRow[55 + nWhichProcedure -1]] * planlogRow[3]) > 0.5:
                            delta = datetime.timedelta(days=1)
                            CurrentProcedureX_Startdatetime += delta
                            CurrentProcedureX_Startdatetime = datetime.datetime.strptime(
                                str(CurrentProcedureX_Startdatetime.date()) + g_MorningStartWorktime, '%Y-%m-%d%H:%M')

                    OneUpdatePlanlogClassList.update_time = datetime.datetime.now()
                    # 计划完工时间
                    OneUpdatePlanlogClassList.jhwg = CurrentProcedureX_Finishdatetime
                    # 追加到列表中以备更新数据库
                    AllUpdatePlanlogClassList_O.append(OneUpdatePlanlogClassList.to_list())
                    # 继续下一个工单
                    break

        return (AllManWorkingArray_O, AllUpdatePlanlogClassList_O, AllSubPlanlogClass)
    except:
        return (AllManWorkingArray_O, AllUpdatePlanlogClassList_O, AllSubPlanlogClass)

# 更新到数据库
def WriteDatabase(startTime, AllVacationContents, AllOvertimeContents):
    conn = pymysql.Connect(
        host=g_DatabaseIP,
        port=dbport,
        user=dbuser,
        passwd=dbpasswd,
        db=database,
        charset='utf8',
        local_infile=1
    )
    # 使用cursor()方法获取操作游标
    cursor = conn.cursor()

    (ret, conn, cursor) = _reConn(conn, cursor)
    if (ret == False):
        return False
    try:
        # 取出所有的procedure_id对应devicetype_id的表
        sql = 'SELECT `id`,`devicetype_id`, `manhours` FROM fa_aps_procedure'
        result = cursor.execute(sql)
        All_ProcedureID2DevicetypeID_Result = ()
        All_ProcedureID2DevicetypeID_dict = {}
        All_ProcedureID2Manhours_dict = {}
        if result:
            # 最完整的所有的结果，每个procedure制程为一个记录，做为最外面的一层循环
            All_ProcedureID2DevicetypeID_Result = cursor.fetchall()
            # 元组转字典，便于后面的查询
            for row in All_ProcedureID2DevicetypeID_Result:
                if row[0] not in All_ProcedureID2DevicetypeID_dict.keys():
                    All_ProcedureID2DevicetypeID_dict[row[0]] = row[1]
                if row[0] not in All_ProcedureID2Manhours_dict.keys():
                    All_ProcedureID2Manhours_dict[row[0]] = row[2]

        # 选取planlog的记录
        # 将datetime变成字符串
        strdatetime = startTime.strftime("'%Y-%m-%d %H:%M'")
        sql = "SELECT PL.`id`, PL.`workorder_id`, WO.`name`, WO.`num`, PL.`finishnum`, PL.`maxnum`, PL.`yjkg`, " \
              "PL.`procedure1_man_id`, PL.`procedure2_man_id`, PL.`procedure3_man_id`, PL.`procedure4_man_id`, " \
              "PL.`procedure5_man_id`, PL.`procedure6_man_id`, PL.`procedure7_man_id`, PL.`procedure8_man_id`, " \
              "PL.`procedure9_man_id`, PL.`procedure10_man_id`, PL.`procedure11_man_id`, PL.`procedure12_man_id`, " \
              "PL.`procedure1_startdate`, PL.`procedure2_startdate`, PL.`procedure3_startdate`, PL.`procedure4_startdate`," \
              "PL.`procedure5_startdate`, PL.`procedure6_startdate`, PL.`procedure7_startdate`, PL.`procedure8_startdate`," \
              "PL.`procedure9_startdate`, PL.`procedure10_startdate`, PL.`procedure11_startdate`, PL.`procedure12_startdate`," \
              "PL.`procedure1_finishdate`, PL.`procedure2_finishdate`, PL.`procedure3_finishdate`, PL.`procedure4_finishdate`," \
              "PL.`procedure5_finishdate`, PL.`procedure6_finishdate`, PL.`procedure7_finishdate`, PL.`procedure8_finishdate`, " \
              "PL.`procedure9_finishdate`, PL.`procedure10_finishdate`, PL.`procedure11_finishdate`, PL.`procedure12_finishdate`, " \
              "PL.`procedure1_manhours`, PL.`procedure2_manhours`, PL.`procedure3_manhours`, PL.`procedure4_manhours`," \
              "PL.`procedure5_manhours`, PL.`procedure6_manhours`, PL.`procedure7_manhours`, PL.`procedure8_manhours`," \
              "PL.`procedure9_manhours`, PL.`procedure10_manhours`, PL.`procedure11_manhours`, PL.`procedure12_manhours`," \
              "PL.`procedure1_id`,  PL.`procedure2_id`, PL.`procedure3_id`, PL.`procedure4_id`," \
              "PL.`procedure5_id`, PL.`procedure6_id`, PL.`procedure7_id`, PL.`procedure8_id`," \
              "PL.`procedure9_id`, PL.`procedure10_id`, PL.`procedure11_id`, PL.`procedure12_id`," \
              "PL.`procedure1_preparedate`,  PL.`procedure2_preparedate`, PL.`procedure3_preparedate`, PL.`procedure4_preparedate`," \
              "PL.`procedure5_preparedate`, PL.`procedure6_preparedate`, PL.`procedure7_preparedate`, PL.`procedure8_preparedate`," \
              "PL.`procedure9_preparedate`, PL.`procedure10_preparedate`, PL.`procedure11_preparedate`, PL.`procedure12_preparedate`, " \
              "PL.`procedure1_mannum`,  PL.`procedure2_mannum`, PL.`procedure3_mannum`, PL.`procedure4_mannum`," \
              "PL.`procedure5_mannum`, PL.`procedure6_mannum`, PL.`procedure7_mannum`, PL.`procedure8_mannum`," \
              "PL.`procedure9_mannum`, PL.`procedure10_mannum`, PL.`procedure11_mannum`, PL.`procedure12_mannum` " \
              "FROM fa_aps_planlog PL LEFT JOIN fa_aps_workorder WO on PL.`workorder_id` = WO.`id` " \
              "WHERE PL.`switch` ='1' AND PL.finishnum < PL.maxnum AND WO.`name` LIKE '5101-%' AND " \
                  "((PL.`procedure1_preparedate` IS NULL OR  PL.`procedure1_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure1_preparedate`) OR " \
                  "(PL.`procedure2_preparedate` IS NULL OR  PL.`procedure2_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure2_preparedate`) OR " \
                  "(PL.`procedure3_preparedate` IS NULL OR  PL.`procedure3_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure3_preparedate`) OR " \
                  "(PL.`procedure4_preparedate` IS NULL OR  PL.`procedure4_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure4_preparedate`) OR " \
                  "(PL.`procedure5_preparedate` IS NULL OR  PL.`procedure5_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure5_preparedate`) OR " \
                  "(PL.`procedure6_preparedate` IS NULL OR  PL.`procedure6_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure6_preparedate`) OR " \
                  "(PL.`procedure7_preparedate` IS NULL OR  PL.`procedure7_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure7_preparedate`) OR " \
                  "(PL.`procedure8_preparedate` IS NULL OR  PL.`procedure8_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure8_preparedate`) OR " \
                  "(PL.`procedure9_preparedate` IS NULL OR  PL.`procedure9_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure9_preparedate`) OR " \
                  "(PL.`procedure10_preparedate` IS NULL OR  PL.`procedure10_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure10_preparedate`) OR " \
                  "(PL.`procedure11_preparedate` IS NULL OR  PL.`procedure11_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure11_preparedate`) OR " \
                  "(PL.`procedure12_preparedate` IS NULL OR  PL.`procedure12_preparedate` ='0000-00-00 00:00:00' OR " + strdatetime + " < PL.`procedure12_preparedate`))"
        # test
        # sql = sql + " AND WO.`name` IN ('5101-202011045','5101-202011046','5101-202101029')"
        result = cursor.execute(sql)

        AllPlanlogResult = ()
        if result:
            # 最完整的所有的结果，每个procedure制程为一个记录，做为最外面的一层循环
            AllPlanlogResult = cursor.fetchall()

        # 列表排序
        AllPlanlogResult = sorted(AllPlanlogResult, key=lambda x: (x[0], x[1]))  # 按列表的第0,1列最迟开始的时间升序排序
        currentPlanLogID = 0  # 当前处理的工单，尽量用同一个人来处理相关的制程

        # 做初始化，取得信息表
        # 1、按制程组成所有的人员：制程ID / 人员 / 开始工作时间点 / 结束工作时间点
        SUMWorkerNums = 0   # 所有可以安排的人数
        (AllManWorkingArray, AllMan2AllDevicetypeIDArray, AllDevicetypeID2ManIDArray, SUMWorkerNums) = GetAllManInfoTable(startTime,
            AllVacationContents, AllPlanlogResult, All_ProcedureID2DevicetypeID_dict)
        # 2、 取得所有按开工时间排好序的工单列表，并区分出急单、未完成的工单、新工单，处理顺序也按这个完成
        # AllSortedWorkorderList = AlartSortedWorkorderList + UnfinishedWorkorderList + NewWorkorderList
        (AllSortedWorkorderList, AlartSortedWorkorderList, UnfinishedWorkorderList, OtherNewWorkorderList) = \
            GetSortedWordorderList(startTime, AllPlanlogResult, AllVacationContents, AllOvertimeContents)

        # 核心排序工单
        AllUpdatePlanlogClassList = []
        # 所有拆分工序的列表，要追加到fa_aps_subplanlog
        AllSubPlanlogClass = []
        # 第一步：先处理急单
        (AllManWorkingArray, AllUpdatePlanlogClassList, AllSubPlanlogClass) = KernelArrangeWorkorder(startTime,
            AlartSortedWorkorderList, All_ProcedureID2DevicetypeID_dict, AllDevicetypeID2ManIDArray, AllPlanlogResult,
            AllManWorkingArray, AllUpdatePlanlogClassList, AllOvertimeContents, AllSubPlanlogClass, All_ProcedureID2Manhours_dict)
        # 第二步：处理未完成工单
        (AllManWorkingArray, AllUpdatePlanlogClassList, AllSubPlanlogClass) = KernelArrangeWorkorder(startTime,
            UnfinishedWorkorderList, All_ProcedureID2DevicetypeID_dict, AllDevicetypeID2ManIDArray, AllPlanlogResult,
            AllManWorkingArray, AllUpdatePlanlogClassList, AllOvertimeContents, AllSubPlanlogClass, All_ProcedureID2Manhours_dict)
        # 第三步：处理新工单
        (AllManWorkingArray, AllUpdatePlanlogClassList, AllSubPlanlogClass) = KernelArrangeWorkorder(startTime,
            OtherNewWorkorderList, All_ProcedureID2DevicetypeID_dict, AllDevicetypeID2ManIDArray, AllPlanlogResult,
            AllManWorkingArray, AllUpdatePlanlogClassList, AllOvertimeContents, AllSubPlanlogClass, All_ProcedureID2Manhours_dict)

        AllUpdatePlanlogClassList = sorted(AllUpdatePlanlogClassList, key=lambda x: (x[49]))

        # 保存旧的planlog到planlog0
        sql = "UPDATE fa_aps_planlog0 A INNER JOIN fa_aps_planlog B ON A.`id` = B.`id` SET A.`workorder_id`=B.`workorder_id`, " \
              "A.`workorder_finishdate`=B.`workorder_finishdate`, A.`pcyqzl`=B.`pcyqzl`, " \
              "A.`procedure1_id`=B.`procedure1_id`, A.`procedure2_id`=B.`procedure2_id`, A.`procedure3_id`=B.`procedure3_id`, " \
              "A.`procedure4_id`=B.`procedure4_id`, A.`procedure5_id`=B.`procedure5_id`, A.`procedure6_id`=B.`procedure6_id`, " \
              "A.`procedure7_id`=B.`procedure7_id`, A.`procedure8_id`=B.`procedure8_id`, A.`procedure9_id`=B.`procedure9_id`, " \
              "A.`procedure10_id`=B.`procedure10_id`, A.`procedure11_id`=B.`procedure11_id`, A.`procedure12_id`=B.`procedure12_id`, " \
              "A.`procedure1_man_id`=B.`procedure1_man_id`, A.`procedure2_man_id`=B.`procedure2_man_id`, " \
              "A.`procedure3_man_id`=B.`procedure3_man_id`, A.`procedure4_man_id`=B.`procedure4_man_id`, " \
              "A.`procedure5_man_id`=B.`procedure5_man_id`, A.`procedure6_man_id`=B.`procedure6_man_id`, " \
              "A.`procedure7_man_id`=B.`procedure7_man_id`, A.`procedure8_man_id`=B.`procedure8_man_id`, " \
              "A.`procedure9_man_id`=B.`procedure9_man_id`, A.`procedure10_man_id`=B.`procedure10_man_id`, " \
              "A.`procedure11_man_id`=B.`procedure11_man_id`, A.`procedure12_man_id`=B.`procedure12_man_id`, " \
              "A.`procedure1_finishdate`=B.`procedure1_finishdate`, A.`procedure2_finishdate`=B.`procedure2_finishdate`, " \
              "A.`procedure3_finishdate`=B.`procedure3_finishdate`, A.`procedure4_finishdate`=B.`procedure4_finishdate`, " \
              "A.`procedure5_finishdate`=B.`procedure5_finishdate`, A.`procedure6_finishdate`=B.`procedure6_finishdate`, " \
              "A.`procedure7_finishdate`=B.`procedure7_finishdate`, A.`procedure8_finishdate`=B.`procedure8_finishdate`, " \
              "A.`procedure9_finishdate`=B.`procedure9_finishdate`, A.`procedure10_finishdate`=B.`procedure10_finishdate`, " \
              "A.`procedure11_finishdate`=B.`procedure11_finishdate`, A.`procedure12_finishdate`=B.`procedure12_finishdate`, " \
              "A.`procedure1_startdate`=B.`procedure1_startdate`, A.`procedure2_startdate`=B.`procedure2_startdate`, " \
              "A.`procedure3_startdate`=B.`procedure3_startdate`, A.`procedure4_startdate`=B.`procedure4_startdate`, " \
              "A.`procedure5_startdate`=B.`procedure5_startdate`, A.`procedure6_startdate`=B.`procedure6_startdate`, " \
              "A.`procedure7_startdate`=B.`procedure7_startdate`, A.`procedure8_startdate`=B.`procedure8_startdate`, " \
              "A.`procedure9_startdate`=B.`procedure9_startdate`, A.`procedure10_startdate`=B.`procedure10_startdate`, " \
              "A.`procedure11_startdate`=B.`procedure11_startdate`, A.`procedure12_startdate`=B.`procedure12_startdate`, " \
              "A.`procedure1_manhours`=B.`procedure1_manhours`, A.`procedure2_manhours`=B.`procedure2_manhours`, " \
              "A.`procedure3_manhours`=B.`procedure3_manhours`, A.`procedure4_manhours`=B.`procedure4_manhours`, " \
              "A.`procedure5_manhours`=B.`procedure5_manhours`, A.`procedure6_manhours`=B.`procedure6_manhours`, " \
              "A.`procedure7_manhours`=B.`procedure7_manhours`, A.`procedure8_manhours`=B.`procedure8_manhours`, " \
              "A.`procedure9_manhours`=B.`procedure9_manhours`, A.`procedure10_manhours`=B.`procedure10_manhours`, " \
              "A.`procedure11_manhours`=B.`procedure11_manhours`, A.`procedure12_manhours`=B.`procedure12_manhours`, " \
              "A.`procedure1_preparedate`=B.`procedure1_preparedate`, A.`procedure2_preparedate`=B.`procedure2_preparedate`, " \
              "A.`procedure3_preparedate`=B.`procedure3_preparedate`, A.`procedure4_preparedate`=B.`procedure4_preparedate`, " \
              "A.`procedure5_preparedate`=B.`procedure5_preparedate`, A.`procedure6_preparedate`=B.`procedure6_preparedate`, " \
              "A.`procedure7_preparedate`=B.`procedure7_preparedate`, A.`procedure8_preparedate`=B.`procedure8_preparedate`, " \
              "A.`procedure9_preparedate`=B.`procedure9_preparedate`, A.`procedure10_preparedate`=B.`procedure10_preparedate`, " \
              "A.`procedure11_preparedate`=B.`procedure11_preparedate`, A.`procedure12_preparedate`=B.`procedure12_preparedate`, " \
              "A.`finishnum`=B.`finishnum`, A.`maxnum`=B.`maxnum`, A.`sjwg`=B.`sjwg`, A.`state`=B.`state`, " \
              "A.`jhwg`=B.`jhwg`, A.`update_time`=B.`update_time`, A.`create_time`=B.`create_time`, " \
              "A.`overtime_hours`=B.`overtime_hours`, A.`yjkg`=B.`yjkg`,  A.`switch`=B.`switch`, " \
              "A.`procedure1_mannum`=B.`procedure1_mannum`, A.`procedure2_mannum`=B.`procedure2_mannum`, " \
              "A.`procedure3_mannum`=B.`procedure3_mannum`, A.`procedure4_mannum`=B.`procedure4_mannum`, " \
              "A.`procedure5_mannum`=B.`procedure5_mannum`, A.`procedure6_mannum`=B.`procedure6_mannum`, " \
              "A.`procedure7_mannum`=B.`procedure7_mannum`, A.`procedure8_mannum`=B.`procedure8_mannum`, " \
              "A.`procedure9_mannum`=B.`procedure9_mannum`, A.`procedure10_mannum`=B.`procedure10_mannum`, " \
              "A.`procedure11_mannum`=B.`procedure11_mannum`, A.`procedure12_mannum`=B.`procedure12_mannum` " \
              "WHERE A.`id` = B.`id`"
        result = cursor.execute(sql)
        conn.commit()
        if result:
            print "fa_aps_planlog0 datebase updates success!"
        # 选择planlog0最后更新的时间，然后将planlog里记录超过该时间的记录全部插入planlog0里，完成对Planlog0的全面更新
        sql = "SELECT update_time FROM fa_aps_planlog0 ORDER BY update_time DESC LIMIT 1"
        result = cursor.execute(sql)
        if result:
            lastUpdatetime = cursor.fetch()
            sql = "SELECT * FROM fa_aps_planlog WHERE update_time > '%s'" % lastUpdatetime
            result = cursor.execute(sql)
            if result:
                All_info_planlog_tuple = cursor.fetchall()

                OneInsertPlanlog0Class = InsertPlanlog0Class()
                AllInsertPlanlog0Class = []     # 插入类
                for row_inner in All_info_planlog_tuple:
                    OneInsertPlanlog0Class.clear()  # 清空
                    OneInsertPlanlog0Class.workorder_id = row_inner[1]
                    OneInsertPlanlog0Class.procedure1_id = row_inner[3]
                    OneInsertPlanlog0Class.procedure2_id = row_inner[4]
                    OneInsertPlanlog0Class.procedure3_id = row_inner[5]
                    OneInsertPlanlog0Class.procedure4_id = row_inner[6]
                    OneInsertPlanlog0Class.procedure5_id = row_inner[7]
                    OneInsertPlanlog0Class.procedure6_id = row_inner[8]
                    OneInsertPlanlog0Class.procedure7_id = row_inner[9]
                    OneInsertPlanlog0Class.procedure8_id = row_inner[10]
                    OneInsertPlanlog0Class.procedure9_id = row_inner[50]
                    OneInsertPlanlog0Class.procedure10_id = row_inner[51]
                    OneInsertPlanlog0Class.procedure11_id = row_inner[52]
                    OneInsertPlanlog0Class.procedure12_id = row_inner[53]   # procedureN_id
                    OneInsertPlanlog0Class.procedure1_man_id = row_inner[11]
                    OneInsertPlanlog0Class.procedure2_man_id = row_inner[12]
                    OneInsertPlanlog0Class.procedure3_man_id = row_inner[13]
                    OneInsertPlanlog0Class.procedure4_man_id = row_inner[14]
                    OneInsertPlanlog0Class.procedure5_man_id = row_inner[15]
                    OneInsertPlanlog0Class.procedure6_man_id = row_inner[16]
                    OneInsertPlanlog0Class.procedure7_man_id = row_inner[17]
                    OneInsertPlanlog0Class.procedure8_man_id = row_inner[18]
                    OneInsertPlanlog0Class.procedure9_man_id = row_inner[54]
                    OneInsertPlanlog0Class.procedure10_man_id = row_inner[55]
                    OneInsertPlanlog0Class.procedure11_man_id = row_inner[56]
                    OneInsertPlanlog0Class.procedure12_man_id = row_inner[57]   # procedureN_man_id
                    OneInsertPlanlog0Class.procedure1_startdate = row_inner[27]
                    OneInsertPlanlog0Class.procedure2_startdate = row_inner[28]
                    OneInsertPlanlog0Class.procedure3_startdate = row_inner[29]
                    OneInsertPlanlog0Class.procedure4_startdate = row_inner[30]
                    OneInsertPlanlog0Class.procedure5_startdate = row_inner[31]
                    OneInsertPlanlog0Class.procedure6_startdate = row_inner[32]
                    OneInsertPlanlog0Class.procedure7_startdate = row_inner[33]
                    OneInsertPlanlog0Class.procedure8_startdate = row_inner[34]
                    OneInsertPlanlog0Class.procedure9_startdate = row_inner[58]
                    OneInsertPlanlog0Class.procedure10_startdate = row_inner[59]
                    OneInsertPlanlog0Class.procedure11_startdate = row_inner[60]
                    OneInsertPlanlog0Class.procedure12_startdate = row_inner[61]   # procedureN_startdate
                    OneInsertPlanlog0Class.procedure1_finishdate = row_inner[19]
                    OneInsertPlanlog0Class.procedure2_finishdate = row_inner[20]
                    OneInsertPlanlog0Class.procedure3_finishdate = row_inner[21]
                    OneInsertPlanlog0Class.procedure4_finishdate = row_inner[22]
                    OneInsertPlanlog0Class.procedure5_finishdate = row_inner[23]
                    OneInsertPlanlog0Class.procedure6_finishdate = row_inner[24]
                    OneInsertPlanlog0Class.procedure7_finishdate = row_inner[25]
                    OneInsertPlanlog0Class.procedure8_finishdate = row_inner[26]
                    OneInsertPlanlog0Class.procedure9_finishdate = row_inner[62]
                    OneInsertPlanlog0Class.procedure10_finishdate = row_inner[63]
                    OneInsertPlanlog0Class.procedure11_finishdate = row_inner[64]
                    OneInsertPlanlog0Class.procedure12_finishdate = row_inner[65]   # procedureN_finishdate
                    OneInsertPlanlog0Class.procedure1_manhours = row_inner[35]
                    OneInsertPlanlog0Class.procedure2_manhours = row_inner[36]
                    OneInsertPlanlog0Class.procedure3_manhours = row_inner[37]
                    OneInsertPlanlog0Class.procedure4_manhours = row_inner[38]
                    OneInsertPlanlog0Class.procedure5_manhours = row_inner[39]
                    OneInsertPlanlog0Class.procedure6_manhours = row_inner[40]
                    OneInsertPlanlog0Class.procedure7_manhours = row_inner[41]
                    OneInsertPlanlog0Class.procedure8_manhours = row_inner[42]
                    OneInsertPlanlog0Class.procedure9_manhours = row_inner[66]
                    OneInsertPlanlog0Class.procedure10_manhours = row_inner[67]
                    OneInsertPlanlog0Class.procedure11_manhours = row_inner[68]
                    OneInsertPlanlog0Class.procedure12_manhours = row_inner[69]   # procedureN_manhours
                    OneInsertPlanlog0Class.procedure1_preparedate = row_inner[70]
                    OneInsertPlanlog0Class.procedure2_preparedate = row_inner[71]
                    OneInsertPlanlog0Class.procedure3_preparedate = row_inner[72]
                    OneInsertPlanlog0Class.procedure4_preparedate = row_inner[73]
                    OneInsertPlanlog0Class.procedure5_preparedate = row_inner[74]
                    OneInsertPlanlog0Class.procedure6_preparedate = row_inner[75]
                    OneInsertPlanlog0Class.procedure7_preparedate = row_inner[76]
                    OneInsertPlanlog0Class.procedure8_preparedate = row_inner[77]
                    OneInsertPlanlog0Class.procedure9_preparedate = row_inner[78]
                    OneInsertPlanlog0Class.procedure10_preparedate = row_inner[79]
                    OneInsertPlanlog0Class.procedure11_preparedate = row_inner[80]
                    OneInsertPlanlog0Class.procedure12_preparedate = row_inner[81]   # procedureN_preparedate
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[85]  # procedure1_mannum
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[86]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[87]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[88]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[89]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[90]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[91]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[92]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[93]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[94]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[95]
                    OneInsertPlanlog0Class.procedure1_mannum = row_inner[96]   #procedure12_mannum
                    OneInsertPlanlog0Class.workorder_finishdate = row_inner[2]
                    OneInsertPlanlog0Class.finishnum = row_inner[43]
                    OneInsertPlanlog0Class.maxnum = row_inner[44]
                    OneInsertPlanlog0Class.create_time = row_inner[49]
                    OneInsertPlanlog0Class.update_time = row_inner[48]
                    OneInsertPlanlog0Class.jhwg = row_inner[47]
                    OneInsertPlanlog0Class.overtime_hours = row_inner[82]
                    OneInsertPlanlog0Class.yjkg = row_inner[83]
                    OneInsertPlanlog0Class.switch = row_inner[84]
                    OneInsertPlanlog0Class.sjwg = row_inner[45]
                    OneInsertPlanlog0Class.state = row_inner[46]
                    OneInsertPlanlog0Class.pcyqzl = row_inner[97]
                    # 追加到列表中
                    AllInsertPlanlog0Class.append(OneInsertPlanlog0Class.to_list())
                # 插入数据库中
                # 再插入数据库
                if len(AllInsertPlanlog0Class) > 0:
                    sql = "insert into fa_aps_planlog0(`workorder_id`," \
                          "`procedure1_id`,`procedure2_id`,`procedure3_id`,`procedure4_id`," \
                          "`procedure5_id`,`procedure6_id`,`procedure7_id`,`procedure8_id`," \
                          "`procedure9_id`,`procedure10_id`,`procedure11_id`,`procedure12_id`," \
                          "`procedure1_man_id`,`procedure2_man_id`,`procedure3_man_id`,`procedure4_man_id`," \
                          "`procedure5_man_id`,`procedure6_man_id`,`procedure7_man_id`,`procedure8_man_id`," \
                          "`procedure9_man_id`,`procedure10_man_id`,`procedure11_man_id`,`procedure12_man_id`," \
                          "`procedure1_startdate`,`procedure2_startdate`,`procedure3_startdate`,`procedure4_startdate`," \
                          "`procedure5_startdate`,`procedure6_startdate`,`procedure7_startdate`,`procedure8_startdate`," \
                          "`procedure9_startdate`,`procedure10_startdate`,`procedure11_startdate`,`procedure12_startdate`," \
                          "`procedure1_finishdate`,`procedure2_finishdate`,`procedure3_finishdate`,`procedure4_finishdate`," \
                          "`procedure5_finishdate`,`procedure6_finishdate`,`procedure7_finishdate`,`procedure8_finishdate`," \
                          "`procedure9_finishdate`,`procedure10_finishdate`,`procedure11_finishdate`,`procedure12_finishdate`," \
                          "`procedure1_manhours`,`procedure2_manhours`,`procedure3_manhours`,`procedure4_manhours`," \
                          "`procedure5_manhours`,`procedure6_manhours`,`procedure7_manhours`,`procedure8_manhours`," \
                          "`procedure9_manhours`,`procedure10_manhours`,`procedure11_manhours`,`procedure12_manhours`," \
                          "`procedure1_preparedate`,`procedure2_preparedate`,`procedure3_preparedate`,`procedure4_preparedate`," \
                          "`procedure5_preparedate`,`procedure6_preparedate`,`procedure7_preparedate`,`procedure8_preparedate`," \
                          "`procedure9_preparedate`,`procedure10_preparedate`,`procedure11_preparedate`,`procedure12_preparedate`," \
                          "`procedure1_mannum`,`procedure2_mannum`,`procedure3_mannum`,`procedure4_mannum`," \
                          "`procedure5_mannum`,`procedure6_mannum`,`procedure7_mannum`,`procedure8_mannum`," \
                          "`procedure9_mannum`,`procedure10_mannum`,`procedure11_mannum`,`procedure12_mannum`," \
                          "`workorder_finishdate`,`finishnum`,`maxnum`,`create_time`,`update_time`,`state`,`jhwg`," \
                          "`overtime_hours`,`yjkg`,`switch`,`sjwg`,`pcyqzl`) " \
                          "values(%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s," \
                          "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
                    result = batchUploadtoDB(sql, AllInsertPlanlog0Class, 100)
                    # result = cursor.executemany(sql, AllInsertPlanlog0Class)
                    if result:
                        print "fa_aps_planlog0 datebase insert success!"

        # 1、第一个数据库：更新到fa_aps_planlog数据库
        # 【0】procedure1_man_id ~ 【11】procedure12_man_id
        # 【12】procedure1_startdate ~ 【23】procedure12_startdate
        # 【24】procedure1_finishdate ~ 【35】procedure12_finishdate
        # 【36】procedure1_manhours ~ 【47】procedure12_manhours
        # 【48】update_time，【49】jhwg， 【50】overtime_hours，【51】planlog_id，【52】workorder_id
        if len(AllUpdatePlanlogClassList) > 0:
            sql = 'UPDATE fa_aps_planlog SET `procedure1_man_id`=%s, `procedure2_man_id`=%s, `procedure3_man_id`=%s, `procedure4_man_id`=%s, ' \
                  '`procedure5_man_id`=%s, `procedure6_man_id`=%s, `procedure7_man_id`=%s, `procedure8_man_id`=%s,' \
                  '`procedure9_man_id`=%s, `procedure10_man_id`=%s, `procedure11_man_id`=%s, `procedure12_man_id`=%s,' \
                  '`procedure1_startdate`=%s, `procedure2_startdate`=%s, `procedure3_startdate`=%s, `procedure4_startdate`=%s, ' \
                  '`procedure5_startdate`=%s, `procedure6_startdate`=%s, `procedure7_startdate`=%s, `procedure8_startdate`=%s,' \
                  '`procedure9_startdate`=%s, `procedure10_startdate`=%s, `procedure11_startdate`=%s, `procedure12_startdate`=%s,' \
                  '`procedure1_finishdate`=%s, `procedure2_finishdate`=%s, `procedure3_finishdate`=%s, `procedure4_finishdate`=%s, ' \
                  '`procedure5_finishdate`=%s, `procedure6_finishdate`=%s, `procedure7_finishdate`=%s, `procedure8_finishdate`=%s, ' \
                  '`procedure9_finishdate`=%s, `procedure10_finishdate`=%s, `procedure11_finishdate`=%s, `procedure12_finishdate`=%s, ' \
                  '`procedure1_manhours`=%s, `procedure2_manhours`=%s, `procedure3_manhours`=%s, `procedure4_manhours`=%s, ' \
                  '`procedure5_manhours`=%s, `procedure6_manhours`=%s, `procedure7_manhours`=%s, `procedure8_manhours`=%s, ' \
                  '`procedure9_manhours`=%s, `procedure10_manhours`=%s, `procedure11_manhours`=%s, `procedure12_manhours`=%s, ' \
                  '`update_time`=%s, `jhwg`=%s, `overtime_hours`=%s  ' \
                  'WHERE `id` = %s and `workorder_id` = %s'
            (ret, conn, cursor) = _reConn(conn, cursor)
            if (ret == False):
                return False
            result = batchUploadtoDB(sql, AllUpdatePlanlogClassList, 50)
            # result = cursor.executemany(sql, AllUpdatePlanlogClassList)
            if result:
                print "fa_aps_planlog datebase updates success!"

        # 统一更新fa_aps_planlog的pcyqzl字段
        sql = "UPDATE `fa_aps_planlog` SET `pcyqzl` = '1' WHERE procedure1_finishdate > jhwg OR procedure2_finishdate > jhwg " \
              "OR procedure3_finishdate > jhwg OR procedure4_finishdate > jhwg OR procedure5_finishdate > jhwg " \
              "OR procedure6_finishdate > jhwg OR procedure6_finishdate > jhwg OR procedure8_finishdate > jhwg " \
              "OR procedure9_finishdate > jhwg OR procedure10_finishdate > jhwg OR procedure11_finishdate > jhwg " \
              "OR procedure12_finishdate > jhwg"
        result = cursor.execute(sql)
        conn.commit()
        print "fa_aps_planlog pcyqzl field updates success!"

        # 3、第3个数据库：插入fa_aps_znpa数据库
        sql = "SELECT `name` FROM fa_aps_znpa"
        result = cursor.execute(sql)
        AllNameZnpa_tuple = ()
        if result:
            AllNameZnpa_tuple = cursor.fetchall()
        AllIDznpa_list = []
        for item in AllNameZnpa_tuple:
            AllIDznpa_list.append(item[0])

        # 再插入
        OneInsertZNPAClass = InsertZNPAClass()
        AllInsertZNPAClass = []
        OneUpdateZNPAClass = UpdateZNPAClass()
        AllUpdateZNPAClass = []
        # 【0】procedure1_man_id ~ 【11】procedure12_man_id
        # 【12】procedure1_startdate ~ 【23】procedure12_startdate
        # 【24】procedure1_finishdate ~ 【35】procedure12_finishdate
        # 【36】procedure1_manhours ~ 【47】procedure12_manhours
        # 【48】update_time，【49】jhwg， 【50】overtime_hours，【51】planlog_id，【52】workorder_id
        for row_outer in AllUpdatePlanlogClassList:
            # 【0】PL.`id`, 【1】PL.`workorder_id`, 【2】WO.`name`, 【3】WO.`number`, 【4】PL.`finishnum`, 【5】PL.`maxnum`，【6】PL.`yjkg`
            # 【7】PL.`procedure1_man_id` ~ 【18】PL.`procedure12_man_id`
            # 【19】PL.`procedure1_startdate` ~ 【30】PL.`procedure12_startdate`
            # 【31】PL.`procedure1_finishdate` ~ 【42】PL.`procedure12_finishdate`
            # 【43】PL.`procedure1_manhours` ~ 【54】PL.`procedure12_manhours`
            # 【55】PL.`procedure1_id` ~ 【66】PL.`procedure12_id`
            # 【67】PL.`procedure1_preparedate` ~ 【78】PL.`procedure12_preparedate`
            # 【79】PL.`procedure1_mannum` ~ 【90】PL.`procedure12_mannum`
            for row_inner in AllPlanlogResult:
                if row_inner[0] == row_outer[51] and row_inner[1] == row_outer[52]:
                    if row_inner[2] not in AllIDznpa_list: # 插入
                        OneInsertZNPAClass.clear()  # 清空
                        OneInsertZNPAClass.name = row_inner[2]
                        OneInsertZNPAClass.workorder_finishdate_new = string_toDatetime(row_outer[24 + row_inner[5] - 1])  # 取新的计划完成时间，即最后一道制程完成的时间
                        if row_inner[31] is None:   # 容错
                            OneInsertZNPAClass.workorder_finishdate = OneInsertZNPAClass.workorder_finishdate_new
                        else:
                            OneInsertZNPAClass.workorder_finishdate = row_inner[31 + row_inner[5] - 1]  # 取前一个排序的计划完成时间，即最后一道制程完成的时间
                        # 追加
                        AllInsertZNPAClass.append(OneInsertZNPAClass.to_list())
                    else:   # 更新
                        OneUpdateZNPAClass.clear()  # 清空
                        OneUpdateZNPAClass.id = row_outer[39]
                        OneUpdateZNPAClass.workorder_finishdate_new = row_outer[24 + row_inner[5] - 1]  # 取新的计划完成时间，即最后一道制程完成的时间
                        # 追加
                        AllUpdateZNPAClass.append(OneUpdateZNPAClass.to_list())

        if len(AllInsertZNPAClass) > 0:
            sql = "insert into fa_aps_znpa(`name`,`workorder_finishdate_new`,`workorder_finishdate`) " \
                  "values(%s,%s,%s)"
            result = batchUploadtoDB(sql, AllInsertZNPAClass, 100)
            # result = cursor.executemany(sql, AllInsertZNPAClass)
            if result:
                print "fa_aps_znpa datebase inserts success!"

        if len(AllUpdateZNPAClass) > 0:
            sql = "UPDATE fa_aps_znpa SET `workorder_finishdate_new`=%s WHERE `id` = %s"
            (ret, conn, cursor) = _reConn(conn, cursor)
            if (ret == False):
                return False
            result = batchUploadtoDB(sql, AllUpdateZNPAClass, 100)
            # result = cursor.executemany(sql, AllUpdateZNPAClass)
            if result:
                print "fa_aps_znpa datebase updates success!"

        # 最后更新排程开关关闭的计划完工时间、开始时间、结束时间、人员ID等，全部清空
        str1 = datetime_toString(datetime.datetime.now())
        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0, " \
              "`procedure12_man_id` =0, `procedure12_startdate` = '0000-00-00 00:00:00', `procedure12_finishdate` = '0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 11"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 10"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 9"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 8"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 7"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 6"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 5"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure5_man_id`=0, `procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure5_startdate`='0000-00-00 00:00:00', `procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure5_finishdate`='0000-00-00 00:00:00', `procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 4"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure4_man_id`=0, " \
              "`procedure5_man_id`=0, `procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure4_startdate`='0000-00-00 00:00:00', " \
              "`procedure5_startdate`='0000-00-00 00:00:00', `procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure4_finishdate`='0000-00-00 00:00:00', " \
              "`procedure5_finishdate`='0000-00-00 00:00:00', `procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 3"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure3_man_id`=0, `procedure4_man_id`=0, " \
              "`procedure5_man_id`=0, `procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure3_startdate`='0000-00-00 00:00:00', `procedure4_startdate`='0000-00-00 00:00:00', " \
              "`procedure5_startdate`='0000-00-00 00:00:00', `procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure3_finishdate`='0000-00-00 00:00:00', `procedure4_finishdate`='0000-00-00 00:00:00', " \
              "`procedure5_finishdate`='0000-00-00 00:00:00', `procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 2"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure2_man_id`=0, `procedure3_man_id`=0, `procedure4_man_id`=0, " \
              "`procedure5_man_id`=0, `procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure2_startdate`='0000-00-00 00:00:00', " \
              "`procedure3_startdate`='0000-00-00 00:00:00', `procedure4_startdate`='0000-00-00 00:00:00', " \
              "`procedure5_startdate`='0000-00-00 00:00:00', `procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure2_finishdate`='0000-00-00 00:00:00', " \
              "`procedure3_finishdate`='0000-00-00 00:00:00', `procedure4_finishdate`='0000-00-00 00:00:00', " \
              "`procedure5_finishdate`='0000-00-00 00:00:00', `procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 1"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        sql = "UPDATE fa_aps_planlog SET `jhwg` = '0000-00-00 00:00:00', " \
              "`overtime_hours`=0.0," \
              "`procedure1_man_id`=0, `procedure2_man_id`=0, `procedure3_man_id`=0, `procedure4_man_id`=0, " \
              "`procedure5_man_id`=0, `procedure6_man_id`=0, `procedure7_man_id`=0, `procedure8_man_id`=0, " \
              "`procedure9_man_id`=0, `procedure10_man_id`=0, `procedure11_man_id`=0, `procedure12_man_id`=0, " \
              "`procedure1_startdate`='0000-00-00 00:00:00', `procedure2_startdate`='0000-00-00 00:00:00', " \
              "`procedure3_startdate`='0000-00-00 00:00:00', `procedure4_startdate`='0000-00-00 00:00:00', " \
              "`procedure5_startdate`='0000-00-00 00:00:00', `procedure6_startdate`='0000-00-00 00:00:00', " \
              "`procedure7_startdate`='0000-00-00 00:00:00', `procedure8_startdate`='0000-00-00 00:00:00', " \
              "`procedure9_startdate`='0000-00-00 00:00:00', `procedure10_startdate`='0000-00-00 00:00:00', " \
              "`procedure11_startdate`='0000-00-00 00:00:00', `procedure12_startdate`='0000-00-00 00:00:00', " \
              "`procedure1_finishdate`='0000-00-00 00:00:00', `procedure2_finishdate`='0000-00-00 00:00:00', " \
              "`procedure3_finishdate`='0000-00-00 00:00:00', `procedure4_finishdate`='0000-00-00 00:00:00', " \
              "`procedure5_finishdate`='0000-00-00 00:00:00', `procedure6_finishdate`='0000-00-00 00:00:00', " \
              "`procedure7_finishdate`='0000-00-00 00:00:00', `procedure8_finishdate`='0000-00-00 00:00:00', " \
              "`procedure9_finishdate`='0000-00-00 00:00:00', `procedure10_finishdate`='0000-00-00 00:00:00', " \
              "`procedure11_finishdate`='0000-00-00 00:00:00', `procedure12_finishdate`='0000-00-00 00:00:00' " \
              "WHERE `switch` = 0 and `finishnum` < `maxnum` and `finishnum` = 0"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        cursor.execute(sql)
        conn.commit()

        # 更新fa_aps_subplanlog表
        sql = "SELECT `planlog_id`,`procedureX_id` FROM fa_aps_subplanlog"
        result = cursor.execute(sql)
        All2IDsubplanlog_tuple = ()
        if result:
            All2IDsubplanlog_tuple = cursor.fetchall()

        OneInsertSubPlanlogClass = SubPlanlogClass()
        AllInsertSubPlanlogClass = []
        OneUpdateSubPlanlogClass = SubPlanlogClass()
        AllUpdateSubPlanlogClass = []
        for row in AllSubPlanlogClass:
            bExistInTuple = False
            for item in All2IDsubplanlog_tuple:
                if row[4] == item[0][0] and row[5] == item[0][1]:
                    bExistInTuple = True
                    break

            if not bExistInTuple:   # 插入
                OneInsertSubPlanlogClass.clear()    # 清空
                OneInsertSubPlanlogClass.man_id = row[0]
                OneInsertSubPlanlogClass.startdate = row[1]
                OneInsertSubPlanlogClass.finishdate = row[2]
                OneInsertSubPlanlogClass.procedureX_manhours = row[3]
                OneInsertSubPlanlogClass.planlog_id = row[4]
                OneInsertSubPlanlogClass.procedureX_id = row[5]
                # 追加到列表
                AllInsertSubPlanlogClass.append(OneInsertSubPlanlogClass.to_list())
            else:   # 更新
                OneUpdateSubPlanlogClass.clear()    # 清空
                OneUpdateSubPlanlogClass.man_id = row[0]
                OneUpdateSubPlanlogClass.startdate = row[1]
                OneUpdateSubPlanlogClass.finishdate = row[2]
                OneUpdateSubPlanlogClass.procedureX_manhours = row[3]
                OneUpdateSubPlanlogClass.planlog_id = row[4]
                OneUpdateSubPlanlogClass.procedureX_id = row[5]
                # 追加到列表
                AllUpdateSubPlanlogClass.append(OneUpdateSubPlanlogClass.to_list())

        if len(AllInsertSubPlanlogClass) > 0:
            sql = "insert into fa_aps_subplanlog(`man_id`,`startdate`,`finishdate`,`procedureX_manhours`,`planlog_id`,`procedureX_id`) " \
                  "values(%s,%s,%s,%s,%s,%s)"
            result = batchUploadtoDB(sql, AllInsertSubPlanlogClass, 100)
            # result = cursor.executemany(sql, AllInsertSubPlanlogClass)
            if result:
                print "fa_aps_subplanlog datebase insert success!"

        # return [self.man_id, datetime_toString(self.startdate), datetime_toString(self.finishdate),
        #         self.procedureX_manhours, self.planlog_id, self.procedureX_id]  # 更新的datetime要转成str格式
        if len(AllUpdateSubPlanlogClass) > 0:
            sql = "UPDATE fa_aps_subplanlog SET `man_id` = %s, `startdate` = %s, `finishdate` = %s, `procedureX_manhours` = %s " \
                  "WHERE `planlog_id` = %s AND `procedureX_id` = %s"
            (ret, conn, cursor) = _reConn(conn, cursor)
            if (ret == False):
                return False
            result = batchUploadtoDB(sql, AllUpdateSubPlanlogClass, 50)
            # result = cursor.executemany(sql, AllUpdateSubPlanlogClass)
            if result:
                print "fa_aps_subplanlog datebase updates success!"

        # 写入到fs_aps_ygyg数据库
        # 【0】procedure1_man_id ~ 【11】procedure12_man_id
        # 【12】procedure1_startdate ~ 【23】procedure12_startdate
        # 【24】procedure1_finishdate ~ 【35】procedure12_finishdate
        # 【36】procedure1_manhours ~ 【47】procedure12_manhours
        # 【48】update_time，【49】jhwg， 【50】overtime_hours，【51】planlog_id，【52】workorder_id
        AllUpdatePlanlogClassList = sorted(AllUpdatePlanlogClassList, key=lambda x: (x[49]))
        LastDay = ""
        if len(AllUpdatePlanlogClassList) > 0:
            LastDay = AllUpdatePlanlogClassList[len(AllUpdatePlanlogClassList)-1][49]   # 计划完工时间
        if WriteToYGYGDatabase(startTime, AllManWorkingArray, AllVacationContents, SUMWorkerNums, LastDay) == False:
            print "WriteToYGYGDatabase failed!"
        # 数据库全部完成，一次性上传数据库
        conn.commit()
        # 关闭数据库
        cursor.close()
        conn.close()

        return True
    except:
        conn.rollback()
        cursor.close()
        conn.close()

        return False

# 写入到fs_aps_ygyg数据库
# AllPlanlogResult:
# 【0】PL.`id`, 【1】PL.`workorder_id`, 【2】WO.`name`, 【3】WO.`number`, 【4】PL.`finishnum`, 【5】PL.`maxnum`，【6】PL.`workorder_finishdate`
# 【7】PL.`procedure1_man_id` ~ 【18】PL.`procedure12_man_id`
# 【19】PL.`procedure1_startdate` ~ 【30】PL.`procedure12_startdate`
# 【31】PL.`procedure1_finishdate` ~ 【42】PL.`procedure12_finishdate`
# 【43】PL.`procedure1_manhours` ~ 【54】PL.`procedure12_manhours`
# 【55】PL.`procedure1_id` ~ 【66】PL.`procedure12_id`
# 【67】PL.`procedure1_preparedate` ~ 【78】PL.`procedure12_preparedate`
# 【79】PL.`procedure1_mannum` ~ 【90】PL.`procedure12_mannum`

# 更新fa_aps_subplanlog表，可以更新也可以插入
class YGYGClass:
    def __init__(self):
        self.gsb = 0.0   # 每日工时百分比
        self.sumAllManhours = 0.0   # 每日所有工作人员的总工时
        self.sumMansPerDay = 0  # 每日工作的总人数
        self.create_time = None  # 创建时间
        self.date = None  # 日期  作为KEY值
    def clear(self):
        self.gsb = 0.0   # 每日工时百分比
        self.sumAllManhours = 0.0  # 每日所有工作人员的总工时
        self.sumMansPerDay = 0  # 每日工作的总人数
        self.create_time = None  # 创建时间
        self.date = None  # 日期  作为KEY值
    def to_list(self):
        return [self.gsb, self.sumAllManhours, self.sumMansPerDay,
                datetime_toString(self.create_time), self.date.strftime("%Y-%m-%d")]  # 更新的datetime要转成str格式
    def __list__(self):
        return [self.gsb, self.sumAllManhours, self.sumMansPerDay,
                datetime_toString(self.create_time), self.date.strftime("%Y-%m-%d")]  # 更新的datetime要转成str格式

# 计算开始和结束日期内的工作时长，单位是小时
def calulateTimeSpawHours(beginDatetime, endDatetime, TimeCursor):
    if endDatetime <= beginDatetime:
        return (0.0, endDatetime)
    # 组合工作日的中午和下午的开始和结束时间点
    (BeginDayMorning_StartTime, BeginDayMorning_EndTime, BeginDayAfternoon_StartTime, BeginDayAfternoon_EndTime, NextDayMorning_StartTime) = \
        composeMonrningAndAfternoon_BeginAndEndtime(TimeCursor)
    # 判断该时间段内（beginDatetime, endDatetime），在该天（CurrentDay）内的时间长度
    # 第1种可能，开始时间点，比当天上午的早上时间还要早
    if beginDatetime < BeginDayMorning_StartTime:
        # 理论上不可能
        if endDatetime <= BeginDayMorning_StartTime:
            return (0.0, BeginDayMorning_StartTime)
        # 结束时间点，在当天的中午时间段
        elif endDatetime > BeginDayMorning_StartTime and endDatetime <= BeginDayMorning_EndTime:
            return ((endDatetime - BeginDayMorning_StartTime).seconds / 3600.0, endDatetime)    # 转换为小时
        # 结束时间点，在当天的中午休息时间段
        elif endDatetime > BeginDayMorning_EndTime and endDatetime <= BeginDayAfternoon_StartTime:
            return ((BeginDayMorning_EndTime - BeginDayMorning_StartTime).seconds / 3600.0, BeginDayAfternoon_StartTime)    # 转换为小时，就是一个上午的时间
        # 结束时间点，在当天的下午工作时间段
        elif endDatetime > BeginDayAfternoon_StartTime and endDatetime <= BeginDayAfternoon_EndTime:
            return (((BeginDayMorning_EndTime - BeginDayMorning_StartTime).seconds +
                    (endDatetime - BeginDayAfternoon_StartTime).seconds) / 3600.0, endDatetime)    # 转换为小时，就是一个上午的时间加上下午的工作时间段
        else:   # 就是一整天
            # 下一天的开始时间
            return (g_PerDayWorkingTime, NextDayMorning_StartTime)
    # 第2种可能，开始时间点，在当天的中午工作时间段
    elif beginDatetime >= BeginDayMorning_StartTime and beginDatetime <= BeginDayMorning_EndTime:
        # 结束时间点也在上午工作时间段
        if endDatetime > BeginDayMorning_StartTime and endDatetime <= BeginDayMorning_EndTime:
            return ((endDatetime - beginDatetime).seconds / 3600.0, endDatetime)   # 转换为小时
        # 结束时间点，在当天的中午休息时间段
        elif endDatetime > BeginDayMorning_EndTime and endDatetime < BeginDayAfternoon_StartTime:
            return ((BeginDayMorning_EndTime - beginDatetime).seconds / 3600.0, BeginDayAfternoon_StartTime)    # 转换为小时，就是一个上午的时间
        # 结束时间点，在当天的下午工作时间段
        elif endDatetime >= BeginDayAfternoon_StartTime and endDatetime <= BeginDayAfternoon_EndTime:
            return (((BeginDayMorning_EndTime - beginDatetime).seconds +
                    (endDatetime - BeginDayAfternoon_StartTime).seconds) / 3600.0, endDatetime)    # 转换为小时，就是一个上午的时间加上下午的工作时间段
        else:   # 就是整个一个下午和上午的工作时间段
            # 下一天的开始时间
            return (((BeginDayMorning_EndTime - beginDatetime).seconds +
                    (BeginDayAfternoon_EndTime - BeginDayAfternoon_StartTime).seconds) / 3600.0, NextDayMorning_StartTime)    # 转换为小时，就是一个上午的时间加上下午的工作时间段
    # 第3种可能，开始时间点，在当天的中午休息时间段
    elif beginDatetime > BeginDayMorning_EndTime and beginDatetime < BeginDayAfternoon_StartTime:
        # 结束时间点也在中午休息时间段
        if endDatetime > BeginDayMorning_EndTime and endDatetime < BeginDayAfternoon_StartTime:
            return (0.0, BeginDayAfternoon_StartTime)
        # 结束时间点，在当天的下午工作时间段
        elif endDatetime >= BeginDayAfternoon_StartTime and endDatetime <= BeginDayAfternoon_EndTime:
            return ((endDatetime - BeginDayAfternoon_StartTime).seconds / 3600.0, endDatetime)  # 就是下午的工作时间段
        else:  # 就是整个一个下午和上午的工作时间段
            # 下一天的开始时间
            return ((BeginDayAfternoon_EndTime - BeginDayAfternoon_StartTime).seconds / 3600.0, NextDayMorning_StartTime)  # 就是一整个下午的工作时间段
    # 第4种可能，开始时间点，在当天的下午工作时间段
    elif beginDatetime >= BeginDayAfternoon_StartTime and beginDatetime <= BeginDayAfternoon_EndTime:
        # 结束时间点，在当天的下午工作时间段
        if endDatetime >= BeginDayAfternoon_StartTime and endDatetime <= BeginDayAfternoon_EndTime:
            return ((endDatetime - beginDatetime).seconds / 3600.0, endDatetime)  # 就是下午的工作时间段
        else:  # 就是整个一个下午和上午的工作时间段
            # 下一天的开始时间
            return ((BeginDayAfternoon_EndTime - beginDatetime).seconds / 3600.0, NextDayMorning_StartTime)  # 就是一整个下午的工作时间段
    # 第5种可能，开始时间点，在当天的下班时间后
    else:
        # 下一天的开始时间
        return (0.0, NextDayMorning_StartTime)

# 组合输入日期的的中午和下午的开始和结束时间
def composeMonrningAndAfternoon_BeginAndEndtime(Currentday):
    # 输入日期的上午工作时间段
    BeginDayMorning_StartTime = datetime.datetime.strptime(str(Currentday.date()) + g_MorningStartWorktime,'%Y-%m-%d%H:%M')
    BeginDayMorning_EndTime = datetime.datetime.strptime(str(Currentday.date()) + g_MorningEndWorktime,'%Y-%m-%d%H:%M')
    # 输入日期的下午工作时间段
    BeginDayAfternoon_StartTime = datetime.datetime.strptime(str(Currentday.date()) + g_AfternoonStartWorktime,'%Y-%m-%d%H:%M')
    BeginDayAfternoon_EndTime = datetime.datetime.strptime(str(Currentday.date()) + g_AfternoonEndWorktime,'%Y-%m-%d%H:%M')

    # 下一天的开始时间
    delta = datetime.timedelta(days=1)
    NextDayMorning_StartTime = BeginDayMorning_StartTime
    NextDayMorning_StartTime += delta

    return (BeginDayMorning_StartTime, BeginDayMorning_EndTime, BeginDayAfternoon_StartTime, BeginDayAfternoon_EndTime,
            NextDayMorning_StartTime)

def WriteToYGYGDatabase(startTime, AllManWorkingArray, AllVacationContents, SUMWorkerNums, strLastDay):
    try:
        conn = pymysql.Connect(
            host=g_DatabaseIP,
            port=dbport,
            user=dbuser,
            passwd=dbpasswd,
            db=database,
            charset='utf8',
            local_infile=1
        )
        # 使用cursor()方法获取操作游标
        cursor = conn.cursor()

        if len(AllManWorkingArray) <= 0:
            print 'no plan...'
            return

        # 没有可以安排的人
        if SUMWorkerNums <= 0:
            print 'no man can be arrange...'
            return

        sql = "DELETE  FROM fa_aps_ygyg"
        (ret, conn, cursor) = _reConn(conn, cursor)
        if (ret == False):
            return False
        result = cursor.execute(sql)
        conn.commit()

        # 按人员的开始和结束时间排列
        # AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[0], x[1], x[2]))
        # 要存储到ygyg表的列表
        AllManWorkingArray = sorted(AllManWorkingArray, key=lambda x: (x[1], x[2]))
        # 先初始化AllYGYGClass，将所有的日期填充好
        # [0] date [1]gsb [2]sumAllManhours [3]sumMansPerDay
        # 从当前时间startTime，到最后一天结束AllManWorkingArray[len(AllManWorkingArray)-1][2]
        CurrentDay = startTime.date()    # AllManWorkingArray不可能为0，前面已经做了判断
        AllYGYGClass = []
        EndDate = AllManWorkingArray[len(AllManWorkingArray)-1][2].date()
        while(True):
            OneYGYGClass = [CurrentDay, 0, SUMWorkerNums * g_PerDayWorkingTime, SUMWorkerNums]
            AllYGYGClass.append(OneYGYGClass)
            CurrentDay = CurrentDay + datetime.timedelta(days = 1)
            if CurrentDay > EndDate:
                break
        Allworkhours = 0.0  # 某个工作日内所有的工作时长，单位是小时
        # [0] date [1]gsb [2]sumAllManhours [3]sumMansPerDay
        for row in AllYGYGClass:
            # AllManWorkingArray按row[1]排的顺序
            for row_inner in AllManWorkingArray:
                if (row[0] >= row_inner[1].date() and row[0] <= row_inner[2].date() ):
                    TimeCursor = datetime.datetime.strptime(str(row[0]), '%Y-%m-%d')
                    (Allworkhours, TimeCursor) = calulateTimeSpawHours(row_inner[1], row_inner[2], TimeCursor)    # 该人在该天的工作时长
                    row[1] += Allworkhours
        # 最后再扣除请假日的时间
        # 【0】`man_id`  【1】`startdate`  【2】`enddate`
        AllYGYGClass = sorted(AllYGYGClass, key=lambda x: (x[0]))
        for row in AllVacationContents:
            # 如果结束时间超过才退出
            # 计算一个工作日内的统计时长
            CurrentDay = row[1]
            TimeCursor = row[1] # 时间游标
            while True:
                # 计算一个工作日内的统计时长
                TimeCursor = AdjustToWorkingHours(TimeCursor, 0, 0, ())
                # 判断处理该行结束标志
                if TimeCursor >= row[2]:
                    # 该行处理结束
                    break
                # 计算当天的休息时长
                CurrentDay = TimeCursor.date()
                if TimeCursor != row[1]:
                    (AllRestWorkhours, TimeCursor) = calulateTimeSpawHours(TimeCursor, row[2], TimeCursor)  # 接下来的时间段，该人在该天的工作时长
                else:
                    (AllRestWorkhours, TimeCursor) = calulateTimeSpawHours(row[1], row[2], TimeCursor)    # 该人在该天的工作时长
                # 从YGYG列表中减去
                # [0] date [1]gsb [2]sumAllManhours [3]sumMansPerDay
                for row_0 in AllYGYGClass:
                    # 找到了，就要减去相应的项
                    if row_0[0] == CurrentDay:
                        if AllRestWorkhours == g_PerDayWorkingTime: # 全天都休息
                            # 全员休息
                            if row[0] == 0:
                                row_0[1] = 0
                                row_0[2] = 0.0
                                row_0[3] = 0
                            else:   # 只是一个人全天休息
                                row_0[2] -= g_PerDayWorkingTime
                                row_0[3] -= 1
                                row_0[1] -= g_PerDayWorkingTime    # 工时比为先保存分子，最后再统一算百分比，累减
                        else:   # 不是全天休息
                            # 全员休息
                            if row[4] == 0:
                                row_0[2] -= AllRestWorkhours*SUMWorkerNums
                                row_0[1] -= AllRestWorkhours*SUMWorkerNums    # 工时比为先保存分子，最后再统一算百分比，累减
                            else:  # 只是一个人休息
                                row_0[2] -= AllRestWorkhours
                                row_0[1] -= AllRestWorkhours  # 工时比为先保存分子，最后再统一算百分比，累减
                        # 统一跳出，继续下一段
                        break

        # 最后写入fa_aps_ygyg数据库
        # YGYGClass：# [0] date [1]gsb [2]sumAllManhours [3]sumMansPerDay
        # 先计算gsb，前面只是分子，要除以分母，即：sumAllManhours，变成百分比，整数
        for row in AllYGYGClass:
            if row[2] > 0.0:
                row[1] = int(row[1]/float(row[2]) * 100)
                if row[1] > row[2]: # 不可能超过总工时
                    row[1] = 100

        # 统一删除[1]gsb [2]sumAllManhours [3]sumMansPerDay 都等于0的项
        i = 0
        LastfinishedDay = datetime.datetime.strptime(strLastDay, '%Y-%m-%d %H:%M').date()
        while i < len(AllYGYGClass):
            # row_0[1] = 0  row_0[2] = 0.0 row_0[3] = 0
            if(AllYGYGClass[i][1] == 0 and AllYGYGClass[i][2] == 0.0 and AllYGYGClass[i][3] == 0):
                AllYGYGClass.pop(i)
                continue
            # 后面的是因为假期添加的，没有必要了
            if AllYGYGClass[i][0] > LastfinishedDay:
                AllYGYGClass.pop(i)
                continue
            i += 1

        # 排除掉休息日
        # [0] date [1]gsb [2]sumAllManhours [3]sumMansPerDay
        for row in g_allVk_v:
            vkTime = datetime.datetime.strptime(row[0] + g_MorningStartWorktime, '%Y-%m-%d%H:%M')
            if vkTime < startTime:
                continue
            for row_inner in AllYGYGClass:
                if datetime.datetime.strptime(row[0], '%Y-%m-%d') == row_inner[0]:  # 如何日期相同，该天要休假
                    row_inner[1] = 0
                    row_inner[2] = 0.0
                    row_inner[3] = 0
                    break

        # 插入数据库
        if len(AllYGYGClass)>0:
            # int(Allworkhours / OneYGYGClass.sumAllManhours * 10000)
            sql = "INSERT INTO fa_aps_ygyg(`date`, `gsb`,`sumAllManhours`,`sumMansPerDay`) " \
                  "values(%s,%s,%s,%s)"
            result = batchUploadtoDB(sql, AllYGYGClass, 200)
            # result = cursor.executemany(sql, AllInsertYGYGClass)
            if result:
                print "fa_aps_ygyg datebase insert success!"
        return True
    except:
        cursor.close()
        conn.close()
        return False
    # end of WriteToYGYGDatabase

#主入口
if __name__ == '__main__':
    global g_allVk_v
    conn = pymysql.Connect(
        host=g_DatabaseIP,
        port=dbport,
        user=dbuser,
        passwd=dbpasswd,
        db=database,
        charset='utf8',
        local_infile=1
    )
    # 使用cursor()方法获取操作游标
    cursor = conn.cursor()
    (ret, conn, cursor) = _reConn(conn, cursor)
    if (ret == False):
        sys.exit()
    # 初始启动时间点
    startTime = datetime.datetime.now()
    startTime = datetime.datetime.strptime(str(startTime.date()) + g_MorningStartWorktime, '%Y-%m-%d%H:%M')

    # 取全员休假表
    sql = "select `v` from fa_aps_vk"
    result = cursor.execute(sql)
    if result:
        g_allVk_v = cursor.fetchall()
        # 判断初始的启动日期是否在休假内
        for row in g_allVk_v:
            vkTime = datetime.datetime.strptime(row[0] + g_MorningStartWorktime, '%Y-%m-%d%H:%M')
            if vkTime < startTime:
                continue

            if startTime == vkTime:
                startTime = startTime + datetime.timedelta(days = 1)
            else:
                break
    # 调整到工作日内
    startTime = AdjustToWorkingHours(startTime, 0, 0, ())  # 开始派单的初始时间，按当前的时间，调整到工作日内

    # 将datetime变成字符串
    strdatetime = startTime.strftime("'%Y-%m-%d %H:%M'")
    # 取所有的休假表
    sql = "select `man_id`,`startdate`,`enddate` from fa_aps_vacationlog where " + strdatetime + "< `enddate`"
    result = cursor.execute(sql)
    AllVacationContents = ()
    if result:
        AllVacationContents = cursor.fetchall()

    # 取所有的加班表
    sql = "select `man_id`,`startdate`,`enddate` from fa_aps_overtimelog where " + strdatetime + "< `enddate`"
    result = cursor.execute(sql)
    AllOvertimeContents = ()
    if result:
        AllOvertimeContents = cursor.fetchall()

    # 写数据库
    if WriteDatabase(startTime, AllVacationContents, AllOvertimeContents) == False:
        sys.exit()